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

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

Former-commit-id: a46915ada5cdd51f6d18ea2f4f367ad1b4bfd445
schuellc 9 жил өмнө
parent
commit
c8e8e19f06
100 өөрчлөгдсөн 5300 нэмэгдсэн , 3333 устгасан
  1. 3 0
      .gitignore
  2. 62 0
      before-submitting-pull-request.md
  3. 3 0
      include/igl/WindingNumberAABB.h
  4. 7 0
      include/igl/WindingNumberTree.h
  5. 5 8
      include/igl/barycenter.h
  6. 0 185
      include/igl/boolean/CSGTree.h
  7. 0 26
      include/igl/boolean/MeshBooleanType.h
  8. 0 38
      include/igl/boolean/from_cork_mesh.h
  9. 0 404
      include/igl/boolean/mesh_boolean.cpp
  10. 0 110
      include/igl/boolean/mesh_boolean.h
  11. 0 54
      include/igl/boolean/mesh_boolean_cork.h
  12. 0 41
      include/igl/boolean/string_to_mesh_boolean_type.h
  13. 0 38
      include/igl/boolean/to_cork_mesh.h
  14. 4 1
      include/igl/boundary_conditions.cpp
  15. 0 28
      include/igl/cgal/RemeshSelfIntersectionsParam.h
  16. 0 34
      include/igl/cgal/assign_scalar.h
  17. 0 44
      include/igl/cgal/complex_to_mesh.h
  18. 0 270
      include/igl/cgal/intersect_other.cpp
  19. 0 106
      include/igl/cgal/intersect_other.h
  20. 0 63
      include/igl/cgal/mesh_to_cgal_triangle_list.cpp
  21. 0 41
      include/igl/cgal/mesh_to_cgal_triangle_list.h
  22. 0 39
      include/igl/cgal/mesh_to_polyhedron.h
  23. 0 393
      include/igl/cgal/order_facets_around_edge.cpp
  24. 0 70
      include/igl/cgal/order_facets_around_edge.h
  25. 0 104
      include/igl/cgal/order_facets_around_edges.h
  26. 0 51
      include/igl/cgal/outer_hull.h
  27. 0 44
      include/igl/cgal/peel_outer_hull_layers.h
  28. 0 85
      include/igl/cgal/point_mesh_squared_distance.h
  29. 0 37
      include/igl/cgal/polyhedron_to_mesh.h
  30. 0 43
      include/igl/cgal/projected_delaunay.h
  31. 0 323
      include/igl/cgal/remesh_intersections.cpp
  32. 0 77
      include/igl/cgal/remesh_intersections.h
  33. 0 92
      include/igl/cgal/remesh_self_intersections.cpp
  34. 0 85
      include/igl/cgal/remesh_self_intersections.h
  35. 0 51
      include/igl/cgal/signed_distance_isosurface.h
  36. 1 0
      include/igl/colon.cpp
  37. 14 0
      include/igl/copyleft/README.md
  38. 131 0
      include/igl/copyleft/boolean/BinaryWindingNumberOperations.h
  39. 188 0
      include/igl/copyleft/boolean/CSGTree.h
  40. 29 0
      include/igl/copyleft/boolean/MeshBooleanType.h
  41. 3 3
      include/igl/copyleft/boolean/from_cork_mesh.cpp
  42. 41 0
      include/igl/copyleft/boolean/from_cork_mesh.h
  43. 296 0
      include/igl/copyleft/boolean/mesh_boolean.cpp
  44. 166 0
      include/igl/copyleft/boolean/mesh_boolean.h
  45. 3 3
      include/igl/copyleft/boolean/mesh_boolean_cork.cpp
  46. 57 0
      include/igl/copyleft/boolean/mesh_boolean_cork.h
  47. 2 2
      include/igl/copyleft/boolean/string_to_mesh_boolean_type.cpp
  48. 44 0
      include/igl/copyleft/boolean/string_to_mesh_boolean_type.h
  49. 3 3
      include/igl/copyleft/boolean/to_cork_mesh.cpp
  50. 41 0
      include/igl/copyleft/boolean/to_cork_mesh.h
  51. 0 0
      include/igl/copyleft/cgal/CGAL_includes.hpp
  52. 31 0
      include/igl/copyleft/cgal/RemeshSelfIntersectionsParam.h
  53. 208 204
      include/igl/copyleft/cgal/SelfIntersectMesh.h
  54. 3 3
      include/igl/copyleft/cgal/assign_scalar.cpp
  55. 37 0
      include/igl/copyleft/cgal/assign_scalar.h
  56. 360 0
      include/igl/copyleft/cgal/closest_facet.cpp
  57. 67 0
      include/igl/copyleft/cgal/closest_facet.h
  58. 8 6
      include/igl/copyleft/cgal/complex_to_mesh.cpp
  59. 47 0
      include/igl/copyleft/cgal/complex_to_mesh.h
  60. 6 6
      include/igl/copyleft/cgal/component_inside_component.cpp
  61. 6 3
      include/igl/copyleft/cgal/component_inside_component.h
  62. 348 0
      include/igl/copyleft/cgal/extract_cells.cpp
  63. 114 0
      include/igl/copyleft/cgal/extract_cells.h
  64. 273 0
      include/igl/copyleft/cgal/intersect_other.cpp
  65. 109 0
      include/igl/copyleft/cgal/intersect_other.h
  66. 65 0
      include/igl/copyleft/cgal/mesh_to_cgal_triangle_list.cpp
  67. 44 0
      include/igl/copyleft/cgal/mesh_to_cgal_triangle_list.h
  68. 2 2
      include/igl/copyleft/cgal/mesh_to_polyhedron.cpp
  69. 42 0
      include/igl/copyleft/cgal/mesh_to_polyhedron.h
  70. 406 0
      include/igl/copyleft/cgal/order_facets_around_edge.cpp
  71. 74 0
      include/igl/copyleft/cgal/order_facets_around_edge.h
  72. 8 8
      include/igl/copyleft/cgal/order_facets_around_edges.cpp
  73. 107 0
      include/igl/copyleft/cgal/order_facets_around_edges.h
  74. 283 0
      include/igl/copyleft/cgal/outer_element.cpp
  75. 115 0
      include/igl/copyleft/cgal/outer_element.h
  76. 7 5
      include/igl/copyleft/cgal/outer_facet.cpp
  77. 6 3
      include/igl/copyleft/cgal/outer_facet.h
  78. 17 19
      include/igl/copyleft/cgal/outer_hull.cpp
  79. 54 0
      include/igl/copyleft/cgal/outer_hull.h
  80. 5 5
      include/igl/copyleft/cgal/peel_outer_hull_layers.cpp
  81. 47 0
      include/igl/copyleft/cgal/peel_outer_hull_layers.h
  82. 33 0
      include/igl/copyleft/cgal/peel_winding_number_layers.cpp
  83. 24 0
      include/igl/copyleft/cgal/peel_winding_number_layers.h
  84. 7 7
      include/igl/copyleft/cgal/point_mesh_squared_distance.cpp
  85. 88 0
      include/igl/copyleft/cgal/point_mesh_squared_distance.h
  86. 31 32
      include/igl/copyleft/cgal/points_inside_component.cpp
  87. 6 3
      include/igl/copyleft/cgal/points_inside_component.h
  88. 2 2
      include/igl/copyleft/cgal/polyhedron_to_mesh.cpp
  89. 40 0
      include/igl/copyleft/cgal/polyhedron_to_mesh.h
  90. 4 4
      include/igl/copyleft/cgal/projected_delaunay.cpp
  91. 46 0
      include/igl/copyleft/cgal/projected_delaunay.h
  92. 263 0
      include/igl/copyleft/cgal/propagate_winding_numbers.cpp
  93. 60 0
      include/igl/copyleft/cgal/propagate_winding_numbers.h
  94. 359 0
      include/igl/copyleft/cgal/remesh_intersections.cpp
  95. 73 0
      include/igl/copyleft/cgal/remesh_intersections.h
  96. 95 0
      include/igl/copyleft/cgal/remesh_self_intersections.cpp
  97. 88 0
      include/igl/copyleft/cgal/remesh_self_intersections.h
  98. 9 10
      include/igl/copyleft/cgal/signed_distance_isosurface.cpp
  99. 54 0
      include/igl/copyleft/cgal/signed_distance_isosurface.h
  100. 16 15
      include/igl/copyleft/marching_cubes.cpp

+ 3 - 0
.gitignore

@@ -21,6 +21,8 @@ example1
 external/yimg/.git*
 external/tinyxml2/CMakeFiles*
 external/tinyxml2/CMakeCache.txt
+external/tinyxml2/cmake_install.cmake
+external/tinyxml2/Makefile
 external/embree/build/*
 external/embree/bin/*
 external/embree/bin
@@ -90,3 +92,4 @@ tests/build
 tests/bin
 python/build3
 *.pyc
+python/build4

+ 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".

+ 3 - 0
include/igl/WindingNumberAABB.h

@@ -126,6 +126,9 @@ inline void igl::WindingNumberAABB<Point>::grow()
 {
   using namespace std;
   using namespace Eigen;
+  // Clear anything that already exists
+  this->delete_children();
+
   //cout<<"cap.rows(): "<<this->getcap().rows()<<endl;
   //cout<<"F.rows(): "<<this->getF().rows()<<endl;
 

+ 7 - 0
include/igl/WindingNumberTree.h

@@ -59,6 +59,7 @@ namespace igl
         const WindingNumberTree<Point> & parent,
         const Eigen::MatrixXi & F);
       inline virtual ~WindingNumberTree();
+      inline void delete_children();
       inline virtual void set_mesh(
         const Eigen::MatrixXd & V,
         const Eigen::MatrixXi & F);
@@ -207,6 +208,12 @@ inline igl::WindingNumberTree<Point>::WindingNumberTree(
 
 template <typename Point>
 inline igl::WindingNumberTree<Point>::~WindingNumberTree()
+{
+  delete_children();
+}
+
+template <typename Point>
+inline void igl::WindingNumberTree<Point>::delete_children()
 {
   using namespace std;
   // Delete children

+ 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 - 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(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;
   }
 

+ 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::__1::vector<CGAL::Triangle_3<CGAL::Epeck>, std::__1::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::__1::vector<CGAL::Triangle_3<CGAL::Epick>, std::__1::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 (faces(i,0) == N+1 && 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(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 (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::__1::vector<int, std::__1::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::__1::vector<int, std::__1::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::__1::vector<int, std::__1::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::__1::vector<int, std::__1::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::__1::vector<int, std::__1::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::__1::vector<int, std::__1::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 - 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 - 323
include/igl/cgal/remesh_intersections.cpp


+ 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

+ 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

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

@@ -0,0 +1,188 @@
+// 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
+      {
+        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
+            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)
+              {
+                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

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

@@ -0,0 +1,296 @@
+// 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>
+
+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) {
+
+  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();
+      resolve_fun(VV, FF, V, F, CJ);
+  }
+
+  // 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; });
+  igl::copyleft::cgal::propagate_winding_numbers(V, F, labels, W);
+  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);
+  }
+
+  // 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);
+  }
+
+  // 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];
+  }
+
+  // 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);
+  }
+}
+
+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

+ 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

+ 208 - 204
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"
@@ -25,199 +25,202 @@
 
 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<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);
+      };
+    }
   }
 }
 
@@ -225,10 +228,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 +275,7 @@ template <
   typename DerivedIF,
   typename DerivedJ,
   typename DerivedIM>
-inline void igl::cgal::SelfIntersectMesh<
+inline void igl::copyleft::cgal::SelfIntersectMesh<
   Kernel,
   DerivedV,
   DerivedF,
@@ -296,7 +300,7 @@ template <
   typename DerivedIF,
   typename DerivedJ,
   typename DerivedIM>
-inline igl::cgal::SelfIntersectMesh<
+inline igl::copyleft::cgal::SelfIntersectMesh<
   Kernel,
   DerivedV,
   DerivedF,
@@ -429,7 +433,7 @@ template <
   typename DerivedIF,
   typename DerivedJ,
   typename DerivedIM>
-inline void igl::cgal::SelfIntersectMesh<
+inline void igl::copyleft::cgal::SelfIntersectMesh<
   Kernel,
   DerivedV,
   DerivedF,
@@ -465,7 +469,7 @@ template <
   typename DerivedIF,
   typename DerivedJ,
   typename DerivedIM>
-inline void igl::cgal::SelfIntersectMesh<
+inline void igl::copyleft::cgal::SelfIntersectMesh<
   Kernel,
   DerivedV,
   DerivedF,
@@ -496,7 +500,7 @@ template <
   typename DerivedIF,
   typename DerivedJ,
   typename DerivedIM>
-inline bool igl::cgal::SelfIntersectMesh<
+inline bool igl::copyleft::cgal::SelfIntersectMesh<
   Kernel,
   DerivedV,
   DerivedF,
@@ -535,7 +539,7 @@ template <
   typename DerivedIF,
   typename DerivedJ,
   typename DerivedIM>
-inline bool igl::cgal::SelfIntersectMesh<
+inline bool igl::copyleft::cgal::SelfIntersectMesh<
   Kernel,
   DerivedV,
   DerivedF,
@@ -581,7 +585,7 @@ template <
   typename DerivedIF,
   typename DerivedJ,
   typename DerivedIM>
-inline bool igl::cgal::SelfIntersectMesh<
+inline bool igl::copyleft::cgal::SelfIntersectMesh<
   Kernel,
   DerivedV,
   DerivedF,
@@ -660,7 +664,7 @@ template <
   typename DerivedIF,
   typename DerivedJ,
   typename DerivedIM>
-inline bool igl::cgal::SelfIntersectMesh<
+inline bool igl::copyleft::cgal::SelfIntersectMesh<
   Kernel,
   DerivedV,
   DerivedF,
@@ -802,7 +806,7 @@ template <
   typename DerivedIF,
   typename DerivedJ,
   typename DerivedIM>
-inline void igl::cgal::SelfIntersectMesh<
+inline void igl::copyleft::cgal::SelfIntersectMesh<
   Kernel,
   DerivedV,
   DerivedF,

+ 3 - 3
include/igl/cgal/assign_scalar.cpp → include/igl/copyleft/cgal/assign_scalar.cpp

@@ -7,21 +7,21 @@
 // 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);
 }
 
-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

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

@@ -0,0 +1,360 @@
+// 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 <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"
+
+template<
+    typename DerivedV,
+    typename DerivedF,
+    typename DerivedI,
+    typename DerivedP,
+    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,
+        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.");
+    }
+
+    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));
+        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) {
+        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:
+                throw std::runtime_error(
+                        "It seems input mesh contains self intersection");
+            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) {
+        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) {
+
+        Point_3 mid_edge_point(
+                (V(s,0) + V(d,0)) * 0.5,
+                (V(s,1) + V(d,1)) * 0.5,
+                (V(s,2) + V(d,2)) * 0.5);
+        Point_3 query_point(
+                P(query_idx, 0),
+                P(query_idx, 1),
+                P(query_idx, 2));
+
+        std::vector<Tree::Primitive_id> intersected_faces;
+        tree.all_intersected_primitives(Segment_3(mid_edge_point, query_point),
+                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::vector<int> intersected_face_signed_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); });
+        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 size_t fid, bool& orientation) {
+        const auto& f = F.row(I(fid, 0));
+        return process_edge_case(query_idx, f[0], f[1], I(fid, 0), orientation);
+    };
+
+    auto process_vertex_case = [&](const size_t query_idx, size_t s,
+            size_t preferred_facet, bool& orientation) {
+        Point_3 closest_point(V(s, 0), V(s, 1), V(s, 2));
+        Point_3 query_point(P(query_idx, 0), P(query_idx, 1), P(query_idx, 2));
+
+        std::vector<Tree::Primitive_id> intersected_faces;
+        tree.all_intersected_primitives(Segment_3(closest_point, query_point),
+                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); });
+
+        std::set<size_t> adj_vertices_set;
+        for (auto fid : intersected_face_indices) {
+            const auto& f = F.row(fid);
+            if ((size_t)f[0] != s) adj_vertices_set.insert(f[0]);
+            if ((size_t)f[1] != s) adj_vertices_set.insert(f[1]);
+            if ((size_t)f[2] != s) adj_vertices_set.insert(f[2]);
+        }
+        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) {
+            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);
+            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()) {
+                    throw std::runtime_error(
+                            "Input mesh contains degenerated faces");
+                }
+                if (is_on_exterior(separator)) {
+                    d = vi;
+                    assert(!CGAL::collinear(
+                                query_point, adj_points[i], closest_point));
+                    break;
+                }
+            }
+        }
+        assert(d != std::numeric_limits<size_t>::max());
+
+        return process_edge_case(query_idx, s, d, preferred_facet, 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, 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 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,
+        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, 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>, 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&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
+#endif

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

@@ -0,0 +1,67 @@
+// 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>
+
+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 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,
+              Eigen::PlainObjectBase<DerivedR>& R,
+              Eigen::PlainObjectBase<DerivedS>& S);
+
+      template<
+          typename DerivedV,
+          typename DerivedF,
+          typename DerivedP,
+          typename DerivedR,
+          typename DerivedS >
+      IGL_INLINE void closest_facet(
+              const Eigen::PlainObjectBase<DerivedV>& V,
+              const Eigen::PlainObjectBase<DerivedF>& F,
+              const Eigen::PlainObjectBase<DerivedP>& P,
+              Eigen::PlainObjectBase<DerivedR>& R,
+              Eigen::PlainObjectBase<DerivedS>& S);
+    }
+  }
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#include "closest_facet.cpp"
+#endif
+#endif

+ 8 - 6
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,7 +16,7 @@
 #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)
@@ -140,12 +140,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

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

@@ -0,0 +1,348 @@
+// 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 "closest_facet.h"
+#include "order_facets_around_edge.h"
+#include "outer_facet.h"
+
+#include <vector>
+#include <queue>
+
+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) {
+    //typedef typename DerivedF::Scalar Index;
+    const size_t num_faces = F.rows();
+    auto edge_index_to_face_index = [&](size_t index) {
+        return index % num_faces;
+    };
+    auto is_consistent = [&](const size_t fid, const size_t s, const size_t d) {
+        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;
+
+    std::vector<std::vector<size_t> > patch_edge_adj(num_patches);
+    std::vector<Eigen::VectorXi> orders(num_unique_edges);
+    std::vector<std::vector<bool> > orientations(num_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 (adj_faces.size() > 2) {
+            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));
+            }
+            auto& order = orders[i];
+            igl::copyleft::cgal::order_facets_around_edge(
+                    V, F, s, d, signed_adj_faces, order);
+            auto& orientation = orientations[i];
+            orientation.resize(order.size());
+            std::transform(order.data(), order.data() + order.size(),
+                    orientation.begin(), [&](int index) { return
+                    signed_adj_faces[index] > 0; });
+            std::transform(order.data(), order.data() + order.size(),
+                    order.data(), [&](int index) { return adj_faces[index]; });
+
+            for (auto ei : adj_faces) {
+                const size_t fid = edge_index_to_face_index(ei);
+                patch_edge_adj[P[fid]].push_back(ei);
+            }
+        }
+    }
+
+    const int INVALID = std::numeric_limits<int>::max();
+    cells.resize(num_patches, 2);
+    cells.setConstant(INVALID);
+
+    auto peel_cell_bd = [&](
+            size_t seed_patch_id,
+            short seed_patch_side,
+            size_t cell_idx) {
+        typedef std::pair<size_t, short> PatchSide;
+        std::queue<PatchSide> Q;
+        Q.emplace(seed_patch_id, seed_patch_side);
+        cells(seed_patch_id, seed_patch_side) = cell_idx;
+        while (!Q.empty()) {
+            auto entry = Q.front();
+            Q.pop();
+            const size_t patch_id = entry.first;
+            const short side = entry.second;
+            const auto& adj_edges = patch_edge_adj[patch_id];
+            for (const auto& ei : adj_edges) {
+                const size_t uei = EMAP[ei];
+                const auto& order = orders[uei];
+                const auto& orientation = orientations[uei];
+                const size_t edge_valance = order.size();
+                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);
+
+                const bool cons = orientation[curr_i];
+                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;
+                }
+                const size_t next_ei = order[next];
+                const bool next_cons = orientation[next];
+                const size_t next_patch_id = P[next_ei % num_faces];
+                const short next_patch_side = (next_cons != cons) ?
+                    side:abs(side-1);
+                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);
+                }
+            }
+        }
+    };
+
+    size_t count=0;
+    for (size_t i=0; i<num_patches; i++) {
+        if (cells(i, 0) == INVALID) {
+            peel_cell_bd(i, 0, count);
+            count++;
+        }
+        if (cells(i, 1) == INVALID) {
+            peel_cell_bd(i, 1, count);
+            count++;
+        }
+    }
+    return count;
+}
+
+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) {
+    const size_t num_faces = F.rows();
+    typedef typename DerivedF::Scalar Index;
+    const size_t num_patches = P.maxCoeff()+1;
+
+    DerivedC raw_cells;
+    const size_t num_raw_cells =
+        igl::copyleft::cgal::extract_cells_single_component(
+                V, F, P, uE, uE2E, EMAP, raw_cells);
+
+    std::vector<std::vector<std::vector<Index > > > TT,_1;
+    igl::triangle_triangle_adjacency(E, EMAP, uE2E, false, TT, _1);
+
+    Eigen::VectorXi C, counts;
+    igl::facet_components(TT, C, counts);
+
+    const size_t num_components = counts.size();
+    std::vector<std::vector<size_t> > components(num_components);
+    for (size_t i=0; i<num_faces; i++) {
+        components[C[i]].push_back(i);
+    }
+    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());
+    }
+
+    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]);
+    }
+
+    auto get_triangle_center = [&](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);
+    if (num_components > 1) {
+        for (size_t i=0; i<num_components; i++) {
+            DerivedV queries(num_components-1, 3);
+            for (size_t j=0; j<num_components; j++) {
+                if (i == j) continue;
+                size_t index = j<i ? j:j-1;
+                queries.row(index) = get_triangle_center(outer_facets[j]);
+            }
+
+            const auto& I = Is[i];
+            Eigen::VectorXi closest_facets, closest_facet_orientations;
+            igl::copyleft::cgal::closest_facet(V, F, I, queries,
+                    closest_facets, closest_facet_orientations);
+
+            for (size_t j=0; j<num_components; j++) {
+                if (i == j) continue;
+                size_t index = j<i ? j:j-1;
+                const size_t closest_patch = P[closest_facets[index]];
+                const size_t closest_patch_side = closest_facet_orientations[index]
+                    ? 0:1;
+                const size_t ambient_cell = raw_cells(closest_patch,
+                        closest_patch_side);
+                if (ambient_cell != (size_t)outer_cells[i]) {
+                    nested_cells[ambient_cell].push_back(outer_cells[j]);
+                    ambient_cells[outer_cells[j]].push_back(ambient_cell);
+                    ambient_comps[j].push_back(i);
+                }
+            }
+        }
+    }
+
+    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);
+    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;
+    return count;
+}
+
+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();
+    //typedef typename DerivedF::Scalar Index;
+
+    Eigen::MatrixXi E, uE;
+    Eigen::VectorXi EMAP;
+    std::vector<std::vector<size_t> > uE2E;
+    igl::unique_edge_map(F, E, uE, EMAP, uE2E);
+
+    Eigen::VectorXi P;
+    //const size_t num_patches = 
+      igl::extract_manifold_patches(F, EMAP, uE2E, P);
+
+    DerivedC per_patch_cells;
+    const size_t num_cells =
+        igl::copyleft::cgal::extract_cells(V, F, P, E, uE, uE2E, EMAP, per_patch_cells);
+
+    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;
+}
+
+#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

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

@@ -0,0 +1,114 @@
+// 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.
+        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.
+        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).  Each
+        // connected component of the mesh partitions the ambient space
+        // separately.
+        //
+        // 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.
+        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 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::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)
+    {
+        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

+ 8 - 8
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,
@@ -304,7 +304,7 @@ IGL_INLINE void igl::cgal::order_facets_around_edges(
 
         Eigen::VectorXi order;
         order_facets_around_edge(V, F, s, d, adj_faces, order);
-        assert(order.size() == edge_valance);
+        assert((size_t)order.size() == edge_valance);
 
         auto& ordered_edges = uE2oE[ui];
         auto& consistency = uE2C[ui];
@@ -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::__1::vector<std::__1::vector<long, std::__1::allocator<long> >, std::__1::allocator<std::__1::vector<long, std::__1::allocator<long> > > > const&, std::__1::vector<std::__1::vector<long, std::__1::allocator<long> >, std::__1::allocator<std::__1::vector<long, std::__1::allocator<long> > > >&, std::__1::vector<std::__1::vector<bool, std::__1::allocator<bool> >, std::__1::allocator<std::__1::vector<bool, std::__1::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::__1::vector<std::__1::vector<long, std::__1::allocator<long> >, std::__1::allocator<std::__1::vector<long, std::__1::allocator<long> > > > const&, std::__1::vector<std::__1::vector<long, std::__1::allocator<long> >, std::__1::allocator<std::__1::vector<long, std::__1::allocator<long> > > >&, std::__1::vector<std::__1::vector<bool, std::__1::allocator<bool> >, std::__1::allocator<std::__1::vector<bool, std::__1::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::__1::vector<std::__1::vector<long, std::__1::allocator<long> >, std::__1::allocator<std::__1::vector<long, std::__1::allocator<long> > > > const&, std::__1::vector<std::__1::vector<long, std::__1::allocator<long> >, std::__1::allocator<std::__1::vector<long, std::__1::allocator<long> > > >&, std::__1::vector<std::__1::vector<bool, std::__1::allocator<bool> >, std::__1::allocator<std::__1::vector<bool, std::__1::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

+ 283 - 0
include/igl/copyleft/cgal/outer_element.cpp

@@ -0,0 +1,283 @@
+// 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 "outer_element.h"
+#include <iostream>
+#include <vector>
+
+template <
+     typename DerivedV,
+     typename DerivedF,
+     typename DerivedI,
+     typename IndexType,
+     typename DerivedA
+     >
+IGL_INLINE void igl::copyleft::cgal::outer_vertex(
+        const Eigen::PlainObjectBase<DerivedV> & V,
+        const Eigen::PlainObjectBase<DerivedF> & F,
+        const Eigen::PlainObjectBase<DerivedI> & I,
+        IndexType & v_index,
+        Eigen::PlainObjectBase<DerivedA> & A)
+{
+    // Algorithm: 
+    //    Find an outer vertex (i.e. vertex reachable from infinity)
+    //    Return the vertex with the largest X value.
+    //    If there is a tie, pick the one with largest Y value.
+    //    If there is still a tie, pick the one with the largest Z value.
+    //    If there is still a tie, then there are duplicated vertices within the
+    //    mesh, which violates the precondition.
+    typedef typename DerivedF::Scalar Index;
+    const Index INVALID = std::numeric_limits<Index>::max();
+    const size_t num_selected_faces = I.rows();
+    std::vector<size_t> candidate_faces;
+    Index outer_vid = INVALID;
+    typename DerivedV::Scalar outer_val = 0;
+    for (size_t i=0; i<num_selected_faces; i++)
+    {
+        size_t f = I(i);
+        for (size_t j=0; j<3; j++)
+        {
+            Index v = F(f, j);
+            auto vx = V(v, 0);
+            if (outer_vid == INVALID || vx > outer_val)
+            {
+                outer_val = vx;
+                outer_vid = v;
+                candidate_faces = {f};
+            } else if (v == outer_vid)
+            {
+                candidate_faces.push_back(f);
+            } else if (vx == outer_val)
+            {
+                // Break tie.
+                auto vy = V(v,1);
+                auto vz = V(v, 2);
+                auto outer_y = V(outer_vid, 1);
+                auto outer_z = V(outer_vid, 2);
+                assert(!(vy == outer_y && vz == outer_z));
+                bool replace = (vy > outer_y) ||
+                    ((vy == outer_y) && (vz > outer_z));
+                if (replace)
+                {
+                    outer_val = vx;
+                    outer_vid = v;
+                    candidate_faces = {f};
+                }
+            }
+        }
+    }
+
+    assert(outer_vid != INVALID);
+    assert(candidate_faces.size() > 0);
+    v_index = outer_vid;
+    A.resize(candidate_faces.size());
+    std::copy(candidate_faces.begin(), candidate_faces.end(), A.data());
+}
+
+template<
+    typename DerivedV,
+    typename DerivedF,
+    typename DerivedI,
+    typename IndexType,
+    typename DerivedA
+    >
+IGL_INLINE void igl::copyleft::cgal::outer_edge(
+        const Eigen::PlainObjectBase<DerivedV> & V,
+        const Eigen::PlainObjectBase<DerivedF> & F,
+        const Eigen::PlainObjectBase<DerivedI> & I,
+        IndexType & v1,
+        IndexType & v2,
+        Eigen::PlainObjectBase<DerivedA> & A) {
+    // Algorithm:
+    //    Find an outer vertex first.
+    //    Find the incident edge with largest abs slope when projected onto XY plane.
+    //    If there is a tie, check the signed slope and use the positive one.
+    //    If there is still a tie, break it using the projected slope onto ZX plane.
+    //    If there is still a tie, again check the signed slope and use the positive one.
+    //    If there is still a tie, then there are multiple overlapping edges,
+    //    which violates the precondition.
+    typedef typename DerivedV::Scalar Scalar;
+    typedef typename DerivedV::Index Index;
+    typedef typename Eigen::Matrix<Scalar, 3, 1> ScalarArray3;
+    typedef typename Eigen::Matrix<typename DerivedF::Scalar, 3, 1> IndexArray3;
+    const Index INVALID = std::numeric_limits<Index>::max();
+
+    Index outer_vid;
+    Eigen::Matrix<Index,Eigen::Dynamic,1> candidate_faces;
+    outer_vertex(V, F, I, outer_vid, candidate_faces);
+    const ScalarArray3& outer_v = V.row(outer_vid);
+    assert(candidate_faces.size() > 0);
+
+    auto get_vertex_index = [&](const IndexArray3& f, Index vid) -> Index 
+    {
+        if (f[0] == vid) return 0;
+        if (f[1] == vid) return 1;
+        if (f[2] == vid) return 2;
+        assert(false);
+        return -1;
+    };
+
+    auto unsigned_value = [](Scalar v) -> Scalar {
+        if (v < 0) return v * -1;
+        else return v;
+    };
+
+    Scalar outer_slope_YX = 0;
+    Scalar outer_slope_ZX = 0;
+    Index outer_opp_vid = INVALID;
+    bool infinite_slope_detected = false;
+    std::vector<Index> incident_faces;
+    auto check_and_update_outer_edge = [&](Index opp_vid, Index fid) {
+        if (opp_vid == outer_opp_vid)
+        {
+            incident_faces.push_back(fid);
+            return;
+        }
+
+        const ScalarArray3 opp_v = V.row(opp_vid);
+        if (!infinite_slope_detected && outer_v[0] != opp_v[0])
+        {
+            // Finite slope
+            const ScalarArray3 diff = opp_v - outer_v;
+            const Scalar slope_YX = diff[1] / diff[0];
+            const Scalar slope_ZX = diff[2] / diff[0];
+            const Scalar u_slope_YX = unsigned_value(slope_YX);
+            const Scalar u_slope_ZX = unsigned_value(slope_ZX);
+            bool update = false;
+            if (outer_opp_vid == INVALID) {
+                update = true;
+            } else {
+                const Scalar u_outer_slope_YX = unsigned_value(outer_slope_YX);
+                if (u_slope_YX > u_outer_slope_YX) {
+                    update = true;
+                } else if (u_slope_YX == u_outer_slope_YX &&
+                        slope_YX > outer_slope_YX) {
+                    update = true;
+                } else if (slope_YX == outer_slope_YX) {
+                    const Scalar u_outer_slope_ZX =
+                        unsigned_value(outer_slope_ZX);
+                    if (u_slope_ZX > u_outer_slope_ZX) {
+                        update = true;
+                    } else if (u_slope_ZX == u_outer_slope_ZX &&
+                            slope_ZX > outer_slope_ZX) {
+                        update = true;
+                    } else if (slope_ZX == u_outer_slope_ZX) {
+                        assert(false);
+                    }
+                }
+            }
+
+            if (update) {
+                outer_opp_vid = opp_vid;
+                outer_slope_YX = slope_YX;
+                outer_slope_ZX = slope_ZX;
+                incident_faces = {fid};
+            }
+        } else if (!infinite_slope_detected)
+        {
+            // Infinite slope
+            outer_opp_vid = opp_vid;
+            infinite_slope_detected = true;
+            incident_faces = {fid};
+        }
+    };
+
+    const size_t num_candidate_faces = candidate_faces.size();
+    for (size_t i=0; i<num_candidate_faces; i++)
+    {
+        const Index fid = candidate_faces(i);
+        const IndexArray3& f = F.row(fid);
+        size_t id = get_vertex_index(f, outer_vid);
+        Index next_vid = f((id+1)%3);
+        Index prev_vid = f((id+2)%3);
+        check_and_update_outer_edge(next_vid, fid);
+        check_and_update_outer_edge(prev_vid, fid);
+    }
+
+    v1 = outer_vid;
+    v2 = outer_opp_vid;
+    A.resize(incident_faces.size());
+    std::copy(incident_faces.begin(), incident_faces.end(), A.data());
+}
+
+template<
+    typename DerivedV,
+    typename DerivedF,
+    typename DerivedN,
+    typename DerivedI,
+    typename IndexType
+    >
+IGL_INLINE void igl::copyleft::cgal::outer_facet(
+        const Eigen::PlainObjectBase<DerivedV> & V,
+        const Eigen::PlainObjectBase<DerivedF> & F,
+        const Eigen::PlainObjectBase<DerivedN> & N,
+        const Eigen::PlainObjectBase<DerivedI> & I,
+        IndexType & f,
+        bool & flipped) {
+    // Algorithm:
+    //    Find an outer edge.
+    //    Find the incident facet with the largest absolute X normal component.
+    //    If there is a tie, keep the one with positive X component.
+    //    If there is still a tie, pick the face with the larger signed index
+    //    (flipped face has negative index).
+    typedef typename DerivedV::Scalar Scalar;
+    typedef typename DerivedV::Index Index;
+    const size_t INVALID = std::numeric_limits<size_t>::max();
+
+    Index v1,v2;
+    Eigen::Matrix<Index,Eigen::Dynamic,1> incident_faces;
+    outer_edge(V, F, I, v1, v2, incident_faces);
+    assert(incident_faces.size() > 0);
+
+    auto generic_fabs = [&](const Scalar& val) -> const Scalar {
+        if (val >= 0) return val;
+        else return -val;
+    };
+
+    Scalar max_nx = 0;
+    size_t outer_fid = INVALID;
+    const size_t num_incident_faces = incident_faces.size();
+    for (size_t i=0; i<num_incident_faces; i++) 
+    {
+        const auto& fid = incident_faces(i);
+        const Scalar nx = N(fid, 0);
+        if (outer_fid == INVALID) {
+            max_nx = nx;
+            outer_fid = fid;
+        } else {
+            if (generic_fabs(nx) > generic_fabs(max_nx)) {
+                max_nx = nx;
+                outer_fid = fid;
+            } else if (nx == -max_nx && nx > 0) {
+                max_nx = nx;
+                outer_fid = fid;
+            } else if (nx == max_nx) {
+                if ((max_nx >= 0 && outer_fid < fid) ||
+                    (max_nx <  0 && outer_fid > fid)) {
+                    max_nx = nx;
+                    outer_fid = fid;
+                }
+            }
+        }
+    }
+
+    assert(outer_fid != INVALID);
+    f = outer_fid;
+    flipped = max_nx < 0;
+}
+
+
+#ifdef IGL_STATIC_LIBRARY
+// Explicit template specialization
+#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
+template void igl::copyleft::cgal::outer_facet<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<long, -1, 1, 0, -1, 1>, int>(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<long, -1, 1, 0, -1, 1> > const&, int&, bool&);
+template void igl::copyleft::cgal::outer_facet<Eigen::Matrix<double, -1, -1, 1, -1, -1>, Eigen::Matrix<int, -1, -1, 1, -1, -1>, Eigen::Matrix<double, -1, -1, 1, -1, -1>, Eigen::Matrix<int, -1, -1, 1, -1, -1>, unsigned long>(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 1, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 1, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 1, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 1, -1, -1> > const&, unsigned long&, bool&);
+template void igl::copyleft::cgal::outer_facet<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, int>(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, int&, bool&);
+template void igl::copyleft::cgal::outer_facet<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>, int>(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, int&, bool&);
+template void igl::copyleft::cgal::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> >&);
+template void igl::copyleft::cgal::outer_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>, long, Eigen::Matrix<long, -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&, long&, long&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&);
+#endif

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

@@ -0,0 +1,115 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2015 Qingan 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_OUTER_ELEMENT_H
+#define IGL_COPYLEFT_CGAL_OUTER_ELEMENT_H
+#include "../../igl_inline.h"
+#include <Eigen/Core>
+namespace igl
+{
+  namespace copyleft
+  {
+    namespace cgal
+    {
+      // Find a vertex that is reachable from infinite without crossing any faces.
+      // Such vertex is called "outer vertex."
+      //
+      // Precondition: The input mesh must have all self-intersection resolved and
+      // no duplicated vertices.  See cgal::remesh_self_intersections.h for how to
+      // obtain such input.
+      //
+      // Inputs:
+      //   V  #V by 3 list of vertex positions
+      //   F  #F by 3 list of triangle indices into V
+      //   I  #I list of facets to consider
+      // Outputs:
+      //   v_index  index of outer vertex
+      //   A  #A list of facets incident to the outer vertex
+      template <
+          typename DerivedV,
+          typename DerivedF,
+          typename DerivedI,
+          typename IndexType,
+          typename DerivedA
+          >
+      IGL_INLINE void outer_vertex(
+              const Eigen::PlainObjectBase<DerivedV> & V,
+              const Eigen::PlainObjectBase<DerivedF> & F,
+              const Eigen::PlainObjectBase<DerivedI> & I,
+              IndexType & v_index,
+              Eigen::PlainObjectBase<DerivedA> & A);
+      // Find an edge that is reachable from infinity without crossing any faces.
+      // Such edge is called "outer edge."
+      //
+      // Precondition: The input mesh must have all self-intersection resolved
+      // and no duplicated vertices.  The correctness of the output depends on
+      // the fact that there is no edge overlap.  See
+      // cgal::remesh_self_intersections.h for how to obtain such input.
+      //
+      // Inputs:
+      //   V  #V by 3 list of vertex positions
+      //   F  #F by 3 list of triangle indices into V
+      //   I  #I list of facets to consider
+      // Outputs:
+      //   v1 index of the first end point of outer edge
+      //   v2 index of the second end point of outer edge
+      //   A  #A list of facets incident to the outer edge
+      template<
+          typename DerivedV,
+          typename DerivedF,
+          typename DerivedI,
+          typename IndexType,
+          typename DerivedA
+          >
+      IGL_INLINE void outer_edge(
+              const Eigen::PlainObjectBase<DerivedV> & V,
+              const Eigen::PlainObjectBase<DerivedF> & F,
+              const Eigen::PlainObjectBase<DerivedI> & I,
+              IndexType & v1,
+              IndexType & v2,
+              Eigen::PlainObjectBase<DerivedA> & A);
+
+
+      // Find a facet that is reachable from infinity without crossing any faces.
+      // Such facet is called "outer facet."
+      //
+      // Precondition: The input mesh must have all self-intersection resolved.
+      // I.e there is no duplicated vertices, no overlapping edge and no
+      // intersecting faces (the only exception is there could be topologically
+      // duplicated faces).  See cgal::remesh_self_intersections.h for how to
+      // obtain such input.
+      //
+      // Inputs:
+      //   V  #V by 3 list of vertex positions
+      //   F  #F by 3 list of triangle indices into V
+      //   N  #N by 3 list of face normals
+      //   I  #I list of facets to consider
+      // Outputs:
+      //   f  Index of the outer facet.
+      //   flipped  true iff the normal of f points inwards.
+      template<
+          typename DerivedV,
+          typename DerivedF,
+          typename DerivedN,
+          typename DerivedI,
+          typename IndexType
+          >
+      IGL_INLINE void outer_facet(
+              const Eigen::PlainObjectBase<DerivedV> & V,
+              const Eigen::PlainObjectBase<DerivedF> & F,
+              const Eigen::PlainObjectBase<DerivedN> & N,
+              const Eigen::PlainObjectBase<DerivedI> & I,
+              IndexType & f,
+              bool & flipped);
+    }
+  }
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "outer_element.cpp"
+#endif
+#endif

+ 7 - 5
include/igl/cgal/outer_facet.cpp → include/igl/copyleft/cgal/outer_facet.cpp

@@ -7,7 +7,7 @@
 // obtain one at http://mozilla.org/MPL/2.0/.
 
 #include "outer_facet.h"
-#include "../outer_element.h"
+#include "outer_element.h"
 #include "order_facets_around_edge.h"
 #include <algorithm>
 #include <CGAL/Exact_predicates_exact_constructions_kernel.h>
@@ -18,7 +18,7 @@ template<
     typename DerivedI,
     typename IndexType
     >
-IGL_INLINE void igl::cgal::outer_facet(
+IGL_INLINE void igl::copyleft::cgal::outer_facet(
         const Eigen::PlainObjectBase<DerivedV> & V,
         const Eigen::PlainObjectBase<DerivedF> & F,
         const Eigen::PlainObjectBase<DerivedI> & I,
@@ -83,7 +83,9 @@ IGL_INLINE void igl::cgal::outer_facet(
 // Explicit template specialization
 #include <CGAL/Exact_predicates_exact_constructions_kernel.h>
 #include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
-template void igl::cgal::outer_facet<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>, int>(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&, int&, bool&);
-template void igl::cgal::outer_facet<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, int>(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<long, -1, 1, 0, -1, 1> > const&, int&, bool&);
-template void igl::cgal::outer_facet<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, int>(Eigen::PlainObjectBase<Eigen::Matrix<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&, int&, bool&);
+template void igl::copyleft::cgal::outer_facet<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>, int>(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&, int&, bool&);
+template void igl::copyleft::cgal::outer_facet<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, int>(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<long, -1, 1, 0, -1, 1> > const&, int&, bool&);
+template void igl::copyleft::cgal::outer_facet<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, int>(Eigen::PlainObjectBase<Eigen::Matrix<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&, int&, bool&);
+template void igl::copyleft::cgal::outer_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>, unsigned long>(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&, unsigned long&, bool&);
+template void igl::copyleft::cgal::outer_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>, int>(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&, int&, bool&);
 #endif

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

@@ -6,13 +6,15 @@
 // 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_FACET_H
-#define IGL_CGAL_OUTER_FACET_H
-#include "../igl_inline.h"
+#ifndef IGL_COPYLEFT_CGAL_OUTER_FACET_H
+#define IGL_COPYLEFT_CGAL_OUTER_FACET_H
+#include "../../igl_inline.h"
 #include <Eigen/Core>
 
 namespace igl
 {
+  namespace copyleft
+  {
     namespace cgal
     {
         // Find a facet that is reachable from infinity without crossing any faces.
@@ -47,6 +49,7 @@ namespace igl
                 bool & flipped);
     }
 
+  }
 }
 
 #ifndef IGL_STATIC_LIBRARY

+ 17 - 19
include/igl/cgal/outer_hull.cpp → include/igl/copyleft/cgal/outer_hull.cpp

@@ -9,16 +9,16 @@
 #include "outer_hull.h"
 #include "order_facets_around_edges.h"
 #include "outer_facet.h"
-#include "../sortrows.h"
-#include "../facet_components.h"
-#include "../winding_number.h"
-#include "../triangle_triangle_adjacency.h"
-#include "../unique_edge_map.h"
-#include "../barycenter.h"
-#include "../per_face_normals.h"
-#include "../writePLY.h"
-#include "../sort_angles.h"
-#include "../writePLY.h"
+#include "../../sortrows.h"
+#include "../../facet_components.h"
+#include "../../winding_number.h"
+#include "../../triangle_triangle_adjacency.h"
+#include "../../unique_edge_map.h"
+#include "../../barycenter.h"
+#include "../../per_face_normals.h"
+#include "../../writePLY.h"
+#include "../../sort_angles.h"
+#include "../../writePLY.h"
 
 #include <Eigen/Geometry>
 #include <vector>
@@ -35,7 +35,7 @@ template <
   typename DerivedG,
   typename DerivedJ,
   typename Derivedflip>
-IGL_INLINE void igl::cgal::outer_hull(
+IGL_INLINE void igl::copyleft::cgal::outer_hull(
   const Eigen::PlainObjectBase<DerivedV> & V,
   const Eigen::PlainObjectBase<DerivedF> & F,
   Eigen::PlainObjectBase<DerivedG> & G,
@@ -159,7 +159,7 @@ IGL_INLINE void igl::cgal::outer_hull(
 #ifdef IGL_OUTER_HULL_DEBUG
   cout<<"outer facet..."<<endl;
 #endif
-  igl::cgal::outer_facet(V,F,IM,f,f_flip);
+  igl::copyleft::cgal::outer_facet(V,F,IM,f,f_flip);
 #ifdef IGL_OUTER_HULL_DEBUG
   cout<<"outer facet: "<<f<<endl;
   //cout << V.row(F(f, 0)) << std::endl;
@@ -329,9 +329,7 @@ IGL_INLINE void igl::cgal::outer_hull(
   // non-intersecting.
   const auto & has_overlapping_bbox = [](
     const Eigen::PlainObjectBase<DerivedV> & V,
-    const MatrixXV & BC,
     const MatrixXG & A,
-    const MatrixXJ & AJ,
     const MatrixXG & B)->bool
   {
     const auto & bounding_box = [](
@@ -387,7 +385,7 @@ IGL_INLINE void igl::cgal::outer_hull(
       {
         continue;
       }
-      if (has_overlapping_bbox(V, BC, vG[id], vJ[id], vG[oid])) {
+      if (has_overlapping_bbox(V, vG[id], vG[oid])) {
           unresolved.push_back(oid);
       }
     }
@@ -401,8 +399,8 @@ IGL_INLINE void igl::cgal::outer_hull(
         query_points(i,2) = (V(f(0,0), 2) + V(f(0,1), 2) + V(f(0,2), 2))/3.0;
     }
     Eigen::VectorXi inside;
-    igl::cgal::points_inside_component(V, vG[id], query_points, inside);
-    assert(inside.size() == num_unresolved_components);
+    igl::copyleft::cgal::points_inside_component(V, vG[id], query_points, inside);
+    assert((size_t)inside.size() == num_unresolved_components);
     for (size_t i=0; i<num_unresolved_components; i++) {
         if (inside(i, 0)) {
             const size_t oid = unresolved[i];
@@ -437,6 +435,6 @@ IGL_INLINE void igl::cgal::outer_hull(
 
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
-template 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> >&);
-template void igl::cgal::outer_hull<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&, 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::copyleft::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> >&);
+template void igl::copyleft::cgal::outer_hull<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&, 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> >&);
 #endif

+ 54 - 0
include/igl/copyleft/cgal/outer_hull.h

@@ -0,0 +1,54 @@
+// 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_OUTER_HULL_H
+#define IGL_COPYLEFT_CGAL_OUTER_HULL_H
+#include "../../igl_inline.h"
+#include <Eigen/Core>
+namespace igl
+{
+  namespace copyleft
+  {
+    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::copyleft::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

+ 5 - 5
include/igl/cgal/peel_outer_hull_layers.cpp → include/igl/copyleft/cgal/peel_outer_hull_layers.cpp

@@ -11,9 +11,9 @@
 #include <iostream>
 //#define IGL_PEEL_OUTER_HULL_LAYERS_DEBUG
 #ifdef IGL_PEEL_OUTER_HULL_LAYERS_DEBUG
-#include "../writePLY.h"
-#include "../writeDMAT.h"
-#include "../STR.h"
+#include "../../writePLY.h"
+#include "../../writeDMAT.h"
+#include "../../STR.h"
 #endif
 
 template <
@@ -21,7 +21,7 @@ template <
   typename DerivedF,
   typename DerivedI,
   typename Derivedflip>
-IGL_INLINE size_t igl::cgal::peel_outer_hull_layers(
+IGL_INLINE size_t igl::copyleft::cgal::peel_outer_hull_layers(
   const Eigen::PlainObjectBase<DerivedV > & V,
   const Eigen::PlainObjectBase<DerivedF > & F,
   Eigen::PlainObjectBase<DerivedI> & I,
@@ -115,5 +115,5 @@ IGL_INLINE size_t igl::cgal::peel_outer_hull_layers(
 
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
-template size_t igl::cgal::peel_outer_hull_layers<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&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
+template size_t igl::copyleft::cgal::peel_outer_hull_layers<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&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 #endif

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

@@ -0,0 +1,47 @@
+// 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_PEEL_OUTER_HULL_LAYERS_H
+#define IGL_COPYLEFT_CGAL_PEEL_OUTER_HULL_LAYERS_H
+#include "../../igl_inline.h"
+#include <Eigen/Core>
+namespace igl
+{
+  namespace copyleft
+  {
+    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

+ 33 - 0
include/igl/copyleft/cgal/peel_winding_number_layers.cpp

@@ -0,0 +1,33 @@
+#include "peel_winding_number_layers.h"
+
+#include <cassert>
+
+#include "propagate_winding_numbers.h"
+
+template<
+typename DerivedV,
+typename DerivedF,
+typename DerivedW >
+IGL_INLINE size_t igl::copyleft::cgal::peel_winding_number_layers(
+        const Eigen::PlainObjectBase<DerivedV > & V,
+        const Eigen::PlainObjectBase<DerivedF > & F,
+        Eigen::PlainObjectBase<DerivedW>& W) {
+    const size_t num_faces = F.rows();
+    Eigen::VectorXi labels(num_faces);
+    labels.setZero();
+
+    Eigen::MatrixXi winding_numbers;
+    igl::copyleft::cgal::propagate_winding_numbers(V, F, labels, winding_numbers);
+    assert(winding_numbers.rows() == num_faces);
+    assert(winding_numbers.cols() == 2);
+
+    int min_w = winding_numbers.minCoeff();
+    int max_w = winding_numbers.maxCoeff();
+    assert(max_w > min_w);
+
+    W.resize(num_faces, 1);
+    for (size_t i=0; i<num_faces; i++) {
+        W(i, 0) = winding_numbers(i, 1);
+    }
+    return max_w - min_w;
+}

+ 24 - 0
include/igl/copyleft/cgal/peel_winding_number_layers.h

@@ -0,0 +1,24 @@
+#ifndef IGL_COPYLEFT_CGAL_PEEL_WINDING_NUMBER_LAYERS_H
+#define IGL_COPYLEFT_CGAL_PEEL_WINDING_NUMBER_LAYERS_H
+#include "../../igl_inline.h"
+#include <Eigen/Core>
+
+namespace igl {
+  namespace copyleft {
+    namespace cgal {
+        template<
+            typename DerivedV,
+            typename DerivedF,
+            typename DerivedW >
+        IGL_INLINE size_t peel_winding_number_layers(
+                const Eigen::PlainObjectBase<DerivedV > & V,
+                const Eigen::PlainObjectBase<DerivedF > & F,
+                Eigen::PlainObjectBase<DerivedW>& W);
+    }
+  }
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "peel_winding_number_layers.cpp"
+#endif
+#endif

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

@@ -9,7 +9,7 @@
 #include "mesh_to_cgal_triangle_list.h"
 
 template <typename Kernel>
-IGL_INLINE void igl::cgal::point_mesh_squared_distance(
+IGL_INLINE void igl::copyleft::cgal::point_mesh_squared_distance(
   const Eigen::MatrixXd & P,
   const Eigen::MatrixXd & V,
   const Eigen::MatrixXi & F,
@@ -30,7 +30,7 @@ IGL_INLINE void igl::cgal::point_mesh_squared_distance(
 }
 
 template <typename Kernel>
-IGL_INLINE void igl::cgal::point_mesh_squared_distance_precompute(
+IGL_INLINE void igl::copyleft::cgal::point_mesh_squared_distance_precompute(
   const Eigen::MatrixXd & V,
   const Eigen::MatrixXi & F,
   CGAL::AABB_tree<
@@ -78,7 +78,7 @@ IGL_INLINE void igl::cgal::point_mesh_squared_distance_precompute(
 }
 
 template <typename Kernel>
-IGL_INLINE void igl::cgal::point_mesh_squared_distance(
+IGL_INLINE void igl::copyleft::cgal::point_mesh_squared_distance(
   const Eigen::MatrixXd & P,
   const CGAL::AABB_tree<
     CGAL::AABB_traits<Kernel, 
@@ -120,8 +120,8 @@ IGL_INLINE void igl::cgal::point_mesh_squared_distance(
 
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
-template void igl::cgal::point_mesh_squared_distance_precompute<CGAL::Epick>(Eigen::Matrix<double, -1, -1, 0, -1, -1> const&, Eigen::Matrix<int, -1, -1, 0, -1, -1> const&, CGAL::AABB_tree<CGAL::AABB_traits<CGAL::Epick, CGAL::AABB_triangle_primitive<CGAL::Epick, std::vector<CGAL::Triangle_3<CGAL::Epick>, std::allocator<CGAL::Triangle_3<CGAL::Epick> > >::iterator, CGAL::Boolean_tag<false> > > >&, std::vector<CGAL::Triangle_3<CGAL::Epick>, std::allocator<CGAL::Triangle_3<CGAL::Epick> > >&);
-template void igl::cgal::point_mesh_squared_distance<CGAL::Epeck>( const Eigen::MatrixXd & P, const Eigen::MatrixXd & V, const Eigen::MatrixXi & F, Eigen::VectorXd & sqrD, Eigen::VectorXi & I, Eigen::MatrixXd & C);
-template void igl::cgal::point_mesh_squared_distance<CGAL::Epick>(Eigen::Matrix<double, -1, -1, 0, -1, -1> const&, Eigen::Matrix<double, -1, -1, 0, -1, -1> const&, Eigen::Matrix<int, -1, -1, 0, -1, -1> const&, Eigen::Matrix<double, -1, 1, 0, -1, 1>&, Eigen::Matrix<int, -1, 1, 0, -1, 1>&, Eigen::Matrix<double, -1, -1, 0, -1, -1>&);
-template void igl::cgal::point_mesh_squared_distance<CGAL::Simple_cartesian<double> >(Eigen::Matrix<double, -1, -1, 0, -1, -1> const&, Eigen::Matrix<double, -1, -1, 0, -1, -1> const&, Eigen::Matrix<int, -1, -1, 0, -1, -1> const&, Eigen::Matrix<double, -1, 1, 0, -1, 1>&, Eigen::Matrix<int, -1, 1, 0, -1, 1>&, Eigen::Matrix<double, -1, -1, 0, -1, -1>&);
+template void igl::copyleft::cgal::point_mesh_squared_distance_precompute<CGAL::Epick>(Eigen::Matrix<double, -1, -1, 0, -1, -1> const&, Eigen::Matrix<int, -1, -1, 0, -1, -1> const&, CGAL::AABB_tree<CGAL::AABB_traits<CGAL::Epick, CGAL::AABB_triangle_primitive<CGAL::Epick, std::vector<CGAL::Triangle_3<CGAL::Epick>, std::allocator<CGAL::Triangle_3<CGAL::Epick> > >::iterator, CGAL::Boolean_tag<false> > > >&, std::vector<CGAL::Triangle_3<CGAL::Epick>, std::allocator<CGAL::Triangle_3<CGAL::Epick> > >&);
+template void igl::copyleft::cgal::point_mesh_squared_distance<CGAL::Epeck>( const Eigen::MatrixXd & P, const Eigen::MatrixXd & V, const Eigen::MatrixXi & F, Eigen::VectorXd & sqrD, Eigen::VectorXi & I, Eigen::MatrixXd & C);
+template void igl::copyleft::cgal::point_mesh_squared_distance<CGAL::Epick>(Eigen::Matrix<double, -1, -1, 0, -1, -1> const&, Eigen::Matrix<double, -1, -1, 0, -1, -1> const&, Eigen::Matrix<int, -1, -1, 0, -1, -1> const&, Eigen::Matrix<double, -1, 1, 0, -1, 1>&, Eigen::Matrix<int, -1, 1, 0, -1, 1>&, Eigen::Matrix<double, -1, -1, 0, -1, -1>&);
+template void igl::copyleft::cgal::point_mesh_squared_distance<CGAL::Simple_cartesian<double> >(Eigen::Matrix<double, -1, -1, 0, -1, -1> const&, Eigen::Matrix<double, -1, -1, 0, -1, -1> const&, Eigen::Matrix<int, -1, -1, 0, -1, -1> const&, Eigen::Matrix<double, -1, 1, 0, -1, 1>&, Eigen::Matrix<int, -1, 1, 0, -1, 1>&, Eigen::Matrix<double, -1, -1, 0, -1, -1>&);
 #endif

+ 88 - 0
include/igl/copyleft/cgal/point_mesh_squared_distance.h

@@ -0,0 +1,88 @@
+// 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_POINT_MESH_SQUARED_DISTANCE_H
+#define IGL_COPYLEFT_CGAL_POINT_MESH_SQUARED_DISTANCE_H
+#include "../../igl_inline.h"
+#include <Eigen/Core>
+#include <vector>
+#include "CGAL_includes.hpp"
+namespace igl
+{
+  namespace copyleft
+  {
+    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

+ 31 - 32
include/igl/cgal/points_inside_component.cpp → include/igl/copyleft/cgal/points_inside_component.cpp

@@ -21,6 +21,8 @@
 #include "assign_scalar.h"
 
 namespace igl {
+  namespace copyleft 
+  {
     namespace cgal {
         namespace points_inside_component_helper {
             typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
@@ -58,9 +60,8 @@ namespace igl {
                 return FACE;
             }
 
-            template<typename DerivedV, typename DerivedF, typename DerivedI>
+            template<typename DerivedF, typename DerivedI>
             void extract_adj_faces(
-                    const Eigen::PlainObjectBase<DerivedV>& V,
                     const Eigen::PlainObjectBase<DerivedF>& F,
                     const Eigen::PlainObjectBase<DerivedI>& I,
                     const size_t s, const size_t d,
@@ -68,24 +69,23 @@ namespace igl {
                 const size_t num_faces = I.rows();
                 for (size_t i=0; i<num_faces; i++) {
                     Eigen::Vector3i f = F.row(I(i, 0));
-                    if ((f[0] == s && f[1] == d) ||
-                        (f[1] == s && f[2] == d) ||
-                        (f[2] == s && f[0] == d)) {
+                    if (((size_t)f[0] == s && (size_t)f[1] == d) ||
+                        ((size_t)f[1] == s && (size_t)f[2] == d) ||
+                        ((size_t)f[2] == s && (size_t)f[0] == d)) {
                         adj_faces.push_back((I(i, 0)+1) * -1);
                         continue;
                     }
-                    if ((f[0] == d && f[1] == s) ||
-                        (f[1] == d && f[2] == s) ||
-                        (f[2] == d && f[0] == s)) {
+                    if (((size_t)f[0] == d && (size_t)f[1] == s) ||
+                        ((size_t)f[1] == d && (size_t)f[2] == s) ||
+                        ((size_t)f[2] == d && (size_t)f[0] == s)) {
                         adj_faces.push_back(I(i, 0)+1);
                         continue;
                     }
                 }
             }
 
-            template<typename DerivedV, typename DerivedF, typename DerivedI>
+            template<typename DerivedF, typename DerivedI>
             void extract_adj_vertices(
-                    const Eigen::PlainObjectBase<DerivedV>& V,
                     const Eigen::PlainObjectBase<DerivedF>& F,
                     const Eigen::PlainObjectBase<DerivedI>& I,
                     const size_t v, std::vector<int>& adj_vertices) {
@@ -93,14 +93,13 @@ namespace igl {
                 const size_t num_faces = I.rows();
                 for (size_t i=0; i<num_faces; i++) {
                     Eigen::Vector3i f = F.row(I(i, 0));
-                    assert((f.array() < V.rows()).all());
-                    if (f[0] == v) {
+                    if ((size_t)f[0] == v) {
                         unique_adj_vertices.insert(f[1]);
                         unique_adj_vertices.insert(f[2]);
-                    } else if (f[1] == v) {
+                    } else if ((size_t)f[1] == v) {
                         unique_adj_vertices.insert(f[0]);
                         unique_adj_vertices.insert(f[2]);
-                    } else if (f[2] == v) {
+                    } else if ((size_t)f[2] == v) {
                         unique_adj_vertices.insert(f[0]);
                         unique_adj_vertices.insert(f[1]);
                     }
@@ -151,18 +150,18 @@ namespace igl {
                 // query point is outside.
 
                 std::vector<int> adj_faces;
-                extract_adj_faces(V, F, I, s, d, adj_faces);
+                extract_adj_faces(F, I, s, d, adj_faces);
                 const size_t num_adj_faces = adj_faces.size();
                 assert(num_adj_faces > 0);
 
                 DerivedV pivot_point(1, 3);
-                igl::cgal::assign_scalar(query.x(), pivot_point(0, 0));
-                igl::cgal::assign_scalar(query.y(), pivot_point(0, 1));
-                igl::cgal::assign_scalar(query.z(), pivot_point(0, 2));
+                igl::copyleft::cgal::assign_scalar(query.x(), pivot_point(0, 0));
+                igl::copyleft::cgal::assign_scalar(query.y(), pivot_point(0, 1));
+                igl::copyleft::cgal::assign_scalar(query.z(), pivot_point(0, 2));
                 Eigen::VectorXi order;
                 order_facets_around_edge(V, F, s, d,
                         adj_faces, pivot_point, order);
-                assert(order.size() == num_adj_faces);
+                assert((size_t)order.size() == num_adj_faces);
                 if (adj_faces[order[0]] > 0 &&
                     adj_faces[order[num_adj_faces-1] < 0]) {
                     return true;
@@ -183,7 +182,7 @@ namespace igl {
                     const Eigen::PlainObjectBase<DerivedI>& I,
                     const Point_3& query, size_t s) {
                 std::vector<int> adj_vertices;
-                extract_adj_vertices(V, F, I, s, adj_vertices);
+                extract_adj_vertices(F, I, s, adj_vertices);
                 const size_t num_adj_vertices = adj_vertices.size();
 
                 std::vector<Point_3> adj_points;
@@ -226,7 +225,6 @@ namespace igl {
                 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++) {
-                        const size_t vj = adj_vertices[j];
                         Plane_3 separator(p, adj_points[i], adj_points[j]);
                         if (separator.is_degenerate()) {
                             throw "Input mesh contains degenerated faces";
@@ -237,9 +235,9 @@ namespace igl {
                             break;
                         }
                     }
-                    if (d < V.rows()) break;
+                    if (d < (size_t)V.rows()) break;
                 }
-                if (d > V.rows()) {
+                if (d > (size_t)V.rows()) {
                     // All adj faces are coplanar, use the first edge.
                     d = adj_vertices[0];
                 }
@@ -267,17 +265,18 @@ namespace igl {
             }
         }
     }
+  }
 }
 
 template<typename DerivedV, typename DerivedF, typename DerivedI,
     typename DerivedP, typename DerivedB>
-IGL_INLINE void igl::cgal::points_inside_component(
+IGL_INLINE void igl::copyleft::cgal::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) {
-    using namespace igl::cgal::points_inside_component_helper;
+    using namespace igl::copyleft::cgal::points_inside_component_helper;
     if (F.rows() <= 0 || I.rows() <= 0) {
         throw "Inside check cannot be done on empty facet component.";
     }
@@ -334,21 +333,21 @@ IGL_INLINE void igl::cgal::points_inside_component(
 
 template<typename DerivedV, typename DerivedF, typename DerivedP,
     typename DerivedB>
-IGL_INLINE void igl::cgal::points_inside_component(
+IGL_INLINE void igl::copyleft::cgal::points_inside_component(
         const Eigen::PlainObjectBase<DerivedV>& V,
         const Eigen::PlainObjectBase<DerivedF>& F,
         const Eigen::PlainObjectBase<DerivedP>& P,
         Eigen::PlainObjectBase<DerivedB>& inside) {
     Eigen::VectorXi I(F.rows());
     I.setLinSpaced(F.rows(), 0, F.rows()-1);
-    igl::cgal::points_inside_component(V, F, I, P, inside);
+    igl::copyleft::cgal::points_inside_component(V, F, I, P, inside);
 }
 
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
-template void igl::cgal::points_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>, 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<   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> >&);
-template void igl::cgal::points_inside_component< 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> >&);
-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> >&);
-template 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> >&);
-template void igl::cgal::points_inside_component<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> >&);
+template void igl::copyleft::cgal::points_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>, 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<   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> >&);
+template void igl::copyleft::cgal::points_inside_component< 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> >&);
+template void igl::copyleft::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> >&);
+template void igl::copyleft::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> >&);
+template void igl::copyleft::cgal::points_inside_component<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> >&);
 #endif

+ 6 - 3
include/igl/cgal/points_inside_component.h → include/igl/copyleft/cgal/points_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 POINTS_INSIDE_COMPONENTS
-#define POINTS_INSIDE_COMPONENTS
+#ifndef IGL_COPYLEFT_CGAL_POINTS_INSIDE_COMPONENTS
+#define IGL_COPYLEFT_CGAL_POINTS_INSIDE_COMPONENTS
 
-#include "../igl_inline.h"
+#include "../../igl_inline.h"
 #include <Eigen/Core>
 #include <vector>
 
 namespace igl {
+  namespace copyleft
+  {
     namespace cgal {
 
         // Determine if queries points P are inside of connected facet component
@@ -51,6 +53,7 @@ namespace igl {
                     const Eigen::PlainObjectBase<DerivedP>& P,
                     Eigen::PlainObjectBase<DerivedB>& inside);
     }
+  }
 }
 
 #ifndef IGL_STATIC_LIBRARY

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

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

+ 40 - 0
include/igl/copyleft/cgal/polyhedron_to_mesh.h

@@ -0,0 +1,40 @@
+// 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_POLYHEDRON_TO_MESH_H
+#define IGL_COPYLEFT_CGAL_POLYHEDRON_TO_MESH_H
+#include "../../igl_inline.h"
+#include <Eigen/Core>
+
+namespace igl
+{
+  namespace copyleft
+  {
+    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

+ 4 - 4
include/igl/cgal/projected_delaunay.cpp → include/igl/copyleft/cgal/projected_delaunay.cpp

@@ -6,7 +6,7 @@
 // v. 2.0. If a copy of the MPL was not distributed with this file, You can 
 // obtain one at http://mozilla.org/MPL/2.0/.
 #include "projected_delaunay.h"
-#include "../REDRUM.h"
+#include "../../REDRUM.h"
 #include <iostream>
 #include <cassert>
 
@@ -15,7 +15,7 @@
 #endif
 
 template <typename Kernel>
-IGL_INLINE void igl::cgal::projected_delaunay(
+IGL_INLINE void igl::copyleft::cgal::projected_delaunay(
   const CGAL::Triangle_3<Kernel> & A,
   const std::vector<CGAL::Object> & A_objects_3,
   CGAL::Constrained_triangulation_plus_2<
@@ -101,6 +101,6 @@ IGL_INLINE void igl::cgal::projected_delaunay(
 
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
-template void igl::cgal::projected_delaunay<CGAL::Epeck>(CGAL::Triangle_3<CGAL::Epeck> const&, std::__1::vector<CGAL::Object, std::__1::allocator<CGAL::Object> > const&, CGAL::Constrained_triangulation_plus_2<CGAL::Constrained_Delaunay_triangulation_2<CGAL::Epeck, CGAL::Triangulation_data_structure_2<CGAL::Triangulation_vertex_base_2<CGAL::Epeck, CGAL::Triangulation_ds_vertex_base_2<void> >, CGAL::Constrained_triangulation_face_base_2<CGAL::Epeck, CGAL::Triangulation_face_base_2<CGAL::Epeck, CGAL::Triangulation_ds_face_base_2<void> > > >, CGAL::Exact_intersections_tag> >&);
-template void igl::cgal::projected_delaunay<CGAL::Epick>(CGAL::Triangle_3<CGAL::Epick> const&, std::__1::vector<CGAL::Object, std::__1::allocator<CGAL::Object> > const&, CGAL::Constrained_triangulation_plus_2<CGAL::Constrained_Delaunay_triangulation_2<CGAL::Epick, CGAL::Triangulation_data_structure_2<CGAL::Triangulation_vertex_base_2<CGAL::Epick, CGAL::Triangulation_ds_vertex_base_2<void> >, CGAL::Constrained_triangulation_face_base_2<CGAL::Epick, CGAL::Triangulation_face_base_2<CGAL::Epick, CGAL::Triangulation_ds_face_base_2<void> > > >, CGAL::Exact_intersections_tag> >&);
+template void igl::copyleft::cgal::projected_delaunay<CGAL::Epeck>(CGAL::Triangle_3<CGAL::Epeck> const&, std::vector<CGAL::Object, std::allocator<CGAL::Object> > const&, CGAL::Constrained_triangulation_plus_2<CGAL::Constrained_Delaunay_triangulation_2<CGAL::Epeck, CGAL::Triangulation_data_structure_2<CGAL::Triangulation_vertex_base_2<CGAL::Epeck, CGAL::Triangulation_ds_vertex_base_2<void> >, CGAL::Constrained_triangulation_face_base_2<CGAL::Epeck, CGAL::Triangulation_face_base_2<CGAL::Epeck, CGAL::Triangulation_ds_face_base_2<void> > > >, CGAL::Exact_intersections_tag> >&);
+template void igl::copyleft::cgal::projected_delaunay<CGAL::Epick>(CGAL::Triangle_3<CGAL::Epick> const&, std::vector<CGAL::Object, std::allocator<CGAL::Object> > const&, CGAL::Constrained_triangulation_plus_2<CGAL::Constrained_Delaunay_triangulation_2<CGAL::Epick, CGAL::Triangulation_data_structure_2<CGAL::Triangulation_vertex_base_2<CGAL::Epick, CGAL::Triangulation_ds_vertex_base_2<void> >, CGAL::Constrained_triangulation_face_base_2<CGAL::Epick, CGAL::Triangulation_face_base_2<CGAL::Epick, CGAL::Triangulation_ds_face_base_2<void> > > >, CGAL::Exact_intersections_tag> >&);
 #endif

+ 46 - 0
include/igl/copyleft/cgal/projected_delaunay.h

@@ -0,0 +1,46 @@
+// 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_PROJECTED_DELAUNAY_H
+#define IGL_COPYLEFT_CGAL_PROJECTED_DELAUNAY_H
+#include "../../igl_inline.h"
+#include "CGAL_includes.hpp"
+namespace igl
+{
+  namespace copyleft
+  {
+    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

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

@@ -0,0 +1,263 @@
+// 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 "propagate_winding_numbers.h"
+#include "../../extract_manifold_patches.h"
+#include "../../extract_non_manifold_edge_curves.h"
+#include "../../facet_components.h"
+#include "../../unique_edge_map.h"
+#include "../../writeOBJ.h"
+#include "../../writePLY.h"
+#include "order_facets_around_edge.h"
+#include "outer_facet.h"
+#include "closest_facet.h"
+#include "assign_scalar.h"
+#include "extract_cells.h"
+
+#include <stdexcept>
+#include <limits>
+#include <vector>
+#include <tuple>
+#include <queue>
+
+namespace propagate_winding_numbers_helper {
+    template<
+        typename DerivedF,
+        typename DeriveduE,
+        typename uE2EType >
+    bool is_orientable(
+            const Eigen::PlainObjectBase<DerivedF>& F,
+            const Eigen::PlainObjectBase<DeriveduE>& uE,
+            const std::vector<std::vector<uE2EType> >& uE2E) {
+        const size_t num_faces = F.rows();
+        const size_t num_edges = uE.rows();
+        auto edge_index_to_face_index = [&](size_t ei) {
+            return ei % num_faces;
+        };
+        auto is_consistent = [&](size_t fid, size_t s, size_t d) {
+            if ((size_t)F(fid, 0) == s && (size_t)F(fid, 1) == d) return true;
+            if ((size_t)F(fid, 1) == s && (size_t)F(fid, 2) == d) return true;
+            if ((size_t)F(fid, 2) == s && (size_t)F(fid, 0) == d) return true;
+
+            if ((size_t)F(fid, 0) == d && (size_t)F(fid, 1) == s) return false;
+            if ((size_t)F(fid, 1) == d && (size_t)F(fid, 2) == s) return false;
+            if ((size_t)F(fid, 2) == d && (size_t)F(fid, 0) == s) return false;
+            throw "Invalid face!!";
+        };
+        for (size_t i=0; i<num_edges; i++) {
+            const size_t s = uE(i,0);
+            const size_t d = uE(i,1);
+            int count=0;
+            for (const auto& ei : uE2E[i]) {
+                const size_t fid = edge_index_to_face_index(ei);
+                if (is_consistent(fid, s, d)) count++;
+                else count--;
+            }
+            if (count != 0) {
+                return false;
+            }
+        }
+        return true;
+    }
+}
+
+template<
+typename DerivedV,
+typename DerivedF,
+typename DerivedL,
+typename DerivedW>
+IGL_INLINE void igl::copyleft::cgal::propagate_winding_numbers(
+        const Eigen::PlainObjectBase<DerivedV>& V,
+        const Eigen::PlainObjectBase<DerivedF>& F,
+        const Eigen::PlainObjectBase<DerivedL>& labels,
+        Eigen::PlainObjectBase<DerivedW>& W) {
+    const size_t num_faces = F.rows();
+    //typedef typename DerivedF::Scalar Index;
+
+    Eigen::MatrixXi E, uE;
+    Eigen::VectorXi EMAP;
+    std::vector<std::vector<size_t> > uE2E;
+    igl::unique_edge_map(F, E, uE, EMAP, uE2E);
+    assert(propagate_winding_numbers_helper::is_orientable(F, uE, uE2E));
+
+    Eigen::VectorXi P;
+    const size_t num_patches = igl::extract_manifold_patches(F, EMAP, uE2E, P);
+
+    DerivedW per_patch_cells;
+    const size_t num_cells =
+        igl::copyleft::cgal::extract_cells(V, F, P, E, uE, uE2E, EMAP, per_patch_cells);
+
+    typedef std::tuple<size_t, bool, size_t> CellConnection;
+    std::vector<std::set<CellConnection> > cell_adjacency(num_cells);
+    for (size_t i=0; i<num_patches; i++) {
+        const int positive_cell = per_patch_cells(i,0);
+        const int negative_cell = per_patch_cells(i,1);
+        cell_adjacency[positive_cell].emplace(negative_cell, false, i);
+        cell_adjacency[negative_cell].emplace(positive_cell, true, i);
+    }
+
+    auto save_cell = [&](const std::string& filename, size_t cell_id) {
+        std::vector<size_t> faces;
+        for (size_t i=0; i<num_patches; i++) {
+            if ((per_patch_cells.row(i).array() == cell_id).any()) {
+                for (size_t j=0; j<num_faces; j++) {
+                    if ((size_t)P[j] == i) {
+                        faces.push_back(j);
+                    }
+                }
+            }
+        }
+        Eigen::MatrixXi cell_faces(faces.size(), 3);
+        for (size_t i=0; i<faces.size(); i++) {
+            cell_faces.row(i) = F.row(faces[i]);
+        }
+        Eigen::MatrixXd vertices(V.rows(), 3);
+        for (size_t i=0; i<(size_t)V.rows(); i++) {
+            assign_scalar(V(i,0), vertices(i,0));
+            assign_scalar(V(i,1), vertices(i,1));
+            assign_scalar(V(i,2), vertices(i,2));
+        }
+        writePLY(filename, vertices, cell_faces);
+    };
+
+    {
+        // Check for odd cycle.
+        Eigen::VectorXi cell_labels(num_cells);
+        cell_labels.setZero();
+        Eigen::VectorXi parents(num_cells);
+        parents.setConstant(-1);
+        auto trace_parents = [&](size_t idx) {
+            std::list<size_t> path;
+            path.push_back(idx);
+            while ((size_t)parents[path.back()] != path.back()) {
+                path.push_back(parents[path.back()]);
+            }
+            return path;
+        };
+        for (size_t i=0; i<num_cells; i++) {
+            if (cell_labels[i] == 0) {
+                cell_labels[i] = 1;
+                std::queue<size_t> Q;
+                Q.push(i);
+                parents[i] = i;
+                while (!Q.empty()) {
+                    size_t curr_idx = Q.front();
+                    Q.pop();
+                    int curr_label = cell_labels[curr_idx];
+                    for (const auto& neighbor : cell_adjacency[curr_idx]) {
+                        if (cell_labels[std::get<0>(neighbor)] == 0) {
+                            cell_labels[std::get<0>(neighbor)] = curr_label * -1;
+                            Q.push(std::get<0>(neighbor));
+                            parents[std::get<0>(neighbor)] = curr_idx;
+                        } else {
+                            if (cell_labels[std::get<0>(neighbor)] !=
+                                    curr_label * -1) {
+                                std::cerr << "Odd cell cycle detected!" << std::endl;
+                                auto path = trace_parents(curr_idx);
+                                path.reverse();
+                                auto path2 = trace_parents(std::get<0>(neighbor));
+                                path.insert(path.end(),
+                                        path2.begin(), path2.end());
+                                for (auto cell_id : path) {
+                                    std::cout << cell_id << " ";
+                                    std::stringstream filename;
+                                    filename << "cell_" << cell_id << ".ply";
+                                    save_cell(filename.str(), cell_id);
+                                }
+                                std::cout << std::endl;
+                            }
+                            assert(cell_labels[std::get<0>(neighbor)] == curr_label * -1);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    size_t outer_facet;
+    bool flipped;
+    Eigen::VectorXi I;
+    I.setLinSpaced(num_faces, 0, num_faces-1);
+    igl::copyleft::cgal::outer_facet(V, F, I, outer_facet, flipped);
+
+    const size_t outer_patch = P[outer_facet];
+    const size_t infinity_cell = per_patch_cells(outer_patch, flipped?1:0);
+
+    Eigen::VectorXi patch_labels(num_patches);
+    const int INVALID = std::numeric_limits<int>::max();
+    patch_labels.setConstant(INVALID);
+    for (size_t i=0; i<num_faces; i++) {
+        if (patch_labels[P[i]] == INVALID) {
+            patch_labels[P[i]] = labels[i];
+        } else {
+            assert(patch_labels[P[i]] == labels[i]);
+        }
+    }
+    assert((patch_labels.array() != INVALID).all());
+    const size_t num_labels = patch_labels.maxCoeff()+1;
+
+    Eigen::MatrixXi per_cell_W(num_cells, num_labels);
+    per_cell_W.setConstant(INVALID);
+    per_cell_W.row(infinity_cell).setZero();
+    std::queue<size_t> Q;
+    Q.push(infinity_cell);
+    while (!Q.empty()) {
+        size_t curr_cell = Q.front();
+        Q.pop();
+        for (const auto& neighbor : cell_adjacency[curr_cell]) {
+            size_t neighbor_cell, patch_idx;
+            bool direction;
+            std::tie(neighbor_cell, direction, patch_idx) = neighbor;
+            if ((per_cell_W.row(neighbor_cell).array() == INVALID).any()) {
+                per_cell_W.row(neighbor_cell) = per_cell_W.row(curr_cell);
+                for (size_t i=0; i<num_labels; i++) {
+                    int inc = (patch_labels[patch_idx] == (int)i) ?
+                        (direction ? -1:1) :0;
+                    per_cell_W(neighbor_cell, i) =
+                        per_cell_W(curr_cell, i) + inc;
+                }
+                Q.push(neighbor_cell);
+            } else {
+                for (size_t i=0; i<num_labels; i++) {
+                    if ((int)i == patch_labels[patch_idx]) {
+#ifndef NDEBUG
+                        int inc = direction ? -1:1;
+                        assert(per_cell_W(neighbor_cell, i) ==
+                                per_cell_W(curr_cell, i) + inc);
+#endif
+                    } else {
+                        assert(per_cell_W(neighbor_cell, i) ==
+                                per_cell_W(curr_cell, i));
+                    }
+                }
+            }
+        }
+    }
+
+    W.resize(num_faces, num_labels*2);
+    for (size_t i=0; i<num_faces; i++) {
+        const size_t patch = P[i];
+        const size_t positive_cell = per_patch_cells(patch, 0);
+        const size_t negative_cell = per_patch_cells(patch, 1);
+        for (size_t j=0; j<num_labels; j++) {
+            W(i,j*2  ) = per_cell_W(positive_cell, j);
+            W(i,j*2+1) = per_cell_W(negative_cell, j);
+        }
+    }
+
+    //for (size_t i=0; i<num_cells; i++) {
+    //    std::stringstream filename;
+    //    filename << "cell_" << i << "_w_" << per_cell_W(i, 1) << ".ply";
+    //    save_cell(filename.str(), i);
+    //}
+}
+
+
+#ifdef IGL_STATIC_LIBRARY
+template void igl::copyleft::cgal::propagate_winding_numbers<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::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> >&);
+#endif

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

@@ -0,0 +1,60 @@
+// 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_PROPAGATE_WINDING_NUMBERS_H
+#define IGL_COPYLEFT_CGAL_PROPAGATE_WINDING_NUMBERS_H
+#include "../../igl_inline.h"
+#include <Eigen/Core>
+#include <vector>
+
+// The following methods compute the winding number on each side of each facet
+// or patch of a 3D mesh.  The input mesh is valid if it splits the ambient
+// space, R^3, into subspaces with constant integer winding numbers.  That is
+// the input mesh should be closed and for each directed edge the number of
+// clockwise facing facets should equal the number of counterclockwise facing
+// facets.
+
+namespace igl {
+  namespace copyleft
+  {
+    namespace cgal {
+
+        // Compute winding number on each side of the face.  The input mesh
+        // could contain multiple connected components.  The input mesh must
+        // represent the boundary of a valid 3D volume, which means it is
+        // closed, consistently oriented and induces integer winding numbers.
+        //
+        // Inputs:
+        //   V  #V by 3 list of vertex positions.
+        //   F  #F by 3 list of triangle indices into V.
+        //   labels  #F list of facet labels ranging from 0 to k-1.
+        //
+        // Output:
+        //   W  #F by k*2 list of winding numbers.  ``W(i,j*2)`` is the winding
+        //      number on the positive side of facet ``i`` with respect to the
+        //      facets labeled ``j``.  Similarly, ``W(i,j*2+1)`` is the winding
+        //      number on the negative side of facet ``i`` with respect to the
+        //      facets labeled ``j``.
+        template<
+            typename DerivedV,
+            typename DerivedF,
+            typename DerivedL,
+            typename DerivedW>
+        IGL_INLINE void propagate_winding_numbers(
+                const Eigen::PlainObjectBase<DerivedV>& V,
+                const Eigen::PlainObjectBase<DerivedF>& F,
+                const Eigen::PlainObjectBase<DerivedL>& labels,
+                Eigen::PlainObjectBase<DerivedW>& W);
+    }
+  }
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "propagate_winding_numbers.cpp"
+#endif
+#endif

+ 359 - 0
include/igl/copyleft/cgal/remesh_intersections.cpp

@@ -0,0 +1,359 @@
+// 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 "remesh_intersections.h"
+#include "assign_scalar.h"
+
+#include <vector>
+#include <map>
+#include <unordered_map>
+#include <iostream>
+
+template <
+typename DerivedV,
+typename DerivedF,
+typename Kernel,
+typename DerivedVV,
+typename DerivedFF,
+typename DerivedJ,
+typename DerivedIM>
+IGL_INLINE void igl::copyleft::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) {
+
+    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 typename DerivedF::Index Index;
+    typedef std::pair<Index, Index> Edge;
+    struct EdgeHash {
+        size_t operator()(const Edge& e) const {
+            return (e.first * 805306457) ^ (e.second * 201326611);
+        }
+    };
+    typedef std::unordered_map<Edge, std::vector<Index>, EdgeHash > EdgeMap;
+
+    auto normalize_plane_coeff = [](const Plane_3& P) {
+        std::vector<typename Kernel::FT> coeffs = {
+            P.a(), P.b(), P.c(), P.d()
+        };
+        const auto max_itr = std::max_element(coeffs.begin(), coeffs.end());
+        const auto min_itr = std::min_element(coeffs.begin(), coeffs.end());
+        typename Kernel::FT max_coeff;
+        if (*max_itr < -1 * *min_itr) {
+            max_coeff = *min_itr;
+        } else {
+            max_coeff = *max_itr;
+        }
+        std::transform(coeffs.begin(), coeffs.end(), coeffs.begin(),
+                [&](const typename Kernel::FT& val)
+                {return val / max_coeff; } );
+        return coeffs;
+    };
+
+    auto plane_comp = [&](const Plane_3& p1, const Plane_3& p2) {
+        const auto p1_coeffs = normalize_plane_coeff(p1);
+        const auto p2_coeffs = normalize_plane_coeff(p2);
+        if (p1_coeffs[0] != p2_coeffs[0])
+            return p1_coeffs[0] < p2_coeffs[0];
+        if (p1_coeffs[1] != p2_coeffs[1])
+            return p1_coeffs[1] < p2_coeffs[1];
+        if (p1_coeffs[2] != p2_coeffs[2])
+            return p1_coeffs[2] < p2_coeffs[2];
+        if (p1_coeffs[3] != p2_coeffs[3])
+            return p1_coeffs[3] < p2_coeffs[3];
+        return false;
+    };
+    std::map<Plane_3, std::vector<Index>, decltype(plane_comp)>
+        unique_planes(plane_comp);
+
+    const size_t num_faces = F.rows();
+    const size_t num_base_vertices = V.rows();
+    assert(num_faces == T.size());
+    std::vector<bool> is_offending(num_faces, false);
+    for (const auto itr : offending) {
+        const auto& fid = itr.first;
+        is_offending[fid] = true;
+
+        Plane_3 key = T[fid].supporting_plane();
+        assert(!key.is_degenerate());
+        const auto jtr = unique_planes.find(key);
+        if (jtr == unique_planes.end()) {
+            unique_planes.insert({key, {fid}});
+        } else {
+            jtr->second.push_back(fid);
+        }
+    }
+
+    std::vector<std::vector<Index> > resolved_faces;
+    std::vector<Index> source_faces;
+    std::vector<Point_3> new_vertices;
+    EdgeMap edge_vertices;
+
+    /**
+     * Run constraint Delaunay triangulation on the plane.
+     */
+    auto run_delaunay_triangulation = [&](const Plane_3& P,
+            const std::vector<Index>& involved_faces,
+            std::vector<Point_3>& vertices,
+            std::vector<std::vector<Index> >& faces) {
+        CDT_plus_2 cdt;
+        for (const auto& fid : involved_faces) {
+            const auto itr = offending.find(fid);
+            const auto& triangle = T[fid];
+            cdt.insert_constraint(P.to_2d(triangle[0]), P.to_2d(triangle[1]));
+            cdt.insert_constraint(P.to_2d(triangle[1]), P.to_2d(triangle[2]));
+            cdt.insert_constraint(P.to_2d(triangle[2]), P.to_2d(triangle[0]));
+
+            if (itr == offending.end()) continue;
+            for (const auto& obj : itr->second.second) {
+                if(const Segment_3 *iseg = CGAL::object_cast<Segment_3 >(&obj)) {
+                    // Add segment constraint
+                    cdt.insert_constraint(
+                            P.to_2d(iseg->vertex(0)),P.to_2d(iseg->vertex(1)));
+                }else if(const Point_3 *ipoint = CGAL::object_cast<Point_3 >(&obj)) {
+                    // Add point
+                    cdt.insert(P.to_2d(*ipoint));
+                } else if(const Triangle_3 *itri = CGAL::object_cast<Triangle_3 >(&obj)) {
+                    // Add 3 segment constraints
+                    cdt.insert_constraint(
+                            P.to_2d(itri->vertex(0)),P.to_2d(itri->vertex(1)));
+                    cdt.insert_constraint(
+                            P.to_2d(itri->vertex(1)),P.to_2d(itri->vertex(2)));
+                    cdt.insert_constraint(
+                            P.to_2d(itri->vertex(2)),P.to_2d(itri->vertex(0)));
+                } else if(const std::vector<Point_3 > *polyp = 
+                        CGAL::object_cast< std::vector<Point_3 > >(&obj)) {
+                    //cerr<<REDRUM("Poly...")<<endl;
+                    const std::vector<Point_3 > & poly = *polyp;
+                    const Index m = poly.size();
+                    assert(m>=2);
+                    for(Index p = 0;p<m;p++)
+                    {
+                        const Index np = (p+1)%m;
+                        cdt.insert_constraint(P.to_2d(poly[p]),P.to_2d(poly[np]));
+                    }
+                }else {
+                    throw std::runtime_error("Unknown intersection object!");
+                }
+            }
+        }
+        std::map<typename CDT_plus_2::Vertex_handle,Index> v2i;
+        size_t count=0;
+        for (auto itr = cdt.finite_vertices_begin();
+                itr != cdt.finite_vertices_end(); itr++) {
+            vertices.push_back(P.to_3d(itr->point()));
+            v2i[itr] = count;
+            count++;
+        }
+        for (auto itr = cdt.finite_faces_begin();
+                itr != cdt.finite_faces_end(); itr++) {
+            faces.push_back( {
+                    v2i[itr->vertex(0)],
+                    v2i[itr->vertex(1)],
+                    v2i[itr->vertex(2)] });
+        }
+    };
+
+    /**
+     * Given p on triangle indexed by ori_f, determine the index of p.
+     */
+    auto determine_point_index = [&](
+            const Point_3& p, const size_t ori_f) -> Index {
+        const auto& triangle = T[ori_f];
+        const auto& f = F.row(ori_f).eval();
+
+        // Check if p is one of the triangle corners.
+        for (size_t i=0; i<3; i++) {
+            if (p == triangle[i]) return f[i];
+        }
+
+        // Check if p is on one of the edges.
+        for (size_t i=0; i<3; i++) {
+            const Point_3 curr_corner = triangle[i];
+            const Point_3 next_corner = triangle[(i+1)%3];
+            const Segment_3 edge(curr_corner, next_corner);
+            if (edge.has_on(p)) {
+                const Index curr = f[i];
+                const Index next = f[(i+1)%3];
+                Edge key;
+                key.first = curr<next?curr:next;
+                key.second = curr<next?next:curr;
+                auto itr = edge_vertices.find(key);
+                if (itr == edge_vertices.end()) {
+                    const Index index =
+                        num_base_vertices + new_vertices.size();
+                    edge_vertices.insert({key, {index}});
+                    new_vertices.push_back(p);
+                    return index;
+                } else {
+                    for (const auto vid : itr->second) {
+                        if (p == new_vertices[vid - num_base_vertices]) {
+                            return vid;
+                        }
+                    }
+                    const size_t index = num_base_vertices + new_vertices.size();
+                    new_vertices.push_back(p);
+                    itr->second.push_back(index);
+                    return index;
+                }
+            }
+        }
+
+        // p must be in the middle of the triangle.
+        const size_t index = num_base_vertices + new_vertices.size();
+        new_vertices.push_back(p);
+        return index;
+    };
+
+    /**
+     * Determine the vertex indices for each corner of each output triangle.
+     */
+    auto post_triangulation_process = [&](
+            const std::vector<Point_3>& vertices,
+            const std::vector<std::vector<Index> >& faces,
+            const std::vector<Index>& involved_faces) {
+        for (const auto& f : faces) {
+            const Point_3& v0 = vertices[f[0]];
+            const Point_3& v1 = vertices[f[1]];
+            const Point_3& v2 = vertices[f[2]];
+            Point_3 center(
+                    (v0[0] + v1[0] + v2[0]) / 3.0,
+                    (v0[1] + v1[1] + v2[1]) / 3.0,
+                    (v0[2] + v1[2] + v2[2]) / 3.0);
+            for (const auto& ori_f : involved_faces) {
+                const auto& triangle = T[ori_f];
+                const Plane_3 P = triangle.supporting_plane();
+                if (triangle.has_on(center)) {
+                    std::vector<Index> corners(3);
+                    corners[0] = determine_point_index(v0, ori_f);
+                    corners[1] = determine_point_index(v1, ori_f);
+                    corners[2] = determine_point_index(v2, ori_f);
+                    if (CGAL::orientation(
+                                P.to_2d(v0), P.to_2d(v1), P.to_2d(v2))
+                            == CGAL::RIGHT_TURN) {
+                        std::swap(corners[0], corners[1]);
+                    }
+                    resolved_faces.emplace_back(corners);
+                    source_faces.push_back(ori_f);
+                }
+            }
+        }
+    };
+
+    // Process un-touched faces.
+    for (size_t i=0; i<num_faces; i++) {
+        if (!is_offending[i]) {
+            resolved_faces.push_back(
+                    { F(i,0), F(i,1), F(i,2) } );
+            source_faces.push_back(i);
+        }
+    }
+
+    // Process self-intersecting faces.
+    for (const auto itr : unique_planes) {
+        Plane_3 P = itr.first;
+        const auto& involved_faces = itr.second;
+
+        std::vector<Point_3> vertices;
+        std::vector<std::vector<Index> > faces;
+        run_delaunay_triangulation(P, involved_faces, vertices, faces);
+        post_triangulation_process(vertices, faces, involved_faces);
+    }
+
+    // Output resolved mesh.
+    const size_t num_out_vertices = new_vertices.size() + num_base_vertices;
+    VV.resize(num_out_vertices, 3);
+    for (size_t i=0; i<num_base_vertices; i++) {
+        assign_scalar(V(i,0), VV(i,0));
+        assign_scalar(V(i,1), VV(i,1));
+        assign_scalar(V(i,2), VV(i,2));
+    }
+    for (size_t i=num_base_vertices; i<num_out_vertices; i++) {
+        assign_scalar(new_vertices[i-num_base_vertices][0], VV(i,0));
+        assign_scalar(new_vertices[i-num_base_vertices][1], VV(i,1));
+        assign_scalar(new_vertices[i-num_base_vertices][2], VV(i,2));
+    }
+
+    const size_t num_out_faces = resolved_faces.size();
+    FF.resize(num_out_faces, 3);
+    for (size_t i=0; i<num_out_faces; i++) {
+        FF(i,0) = resolved_faces[i][0];
+        FF(i,1) = resolved_faces[i][1];
+        FF(i,2) = resolved_faces[i][2];
+    }
+
+    J.resize(num_out_faces);
+    std::copy(source_faces.begin(), source_faces.end(), J.data());
+
+    // Extract unique vertex indices.
+    IM.resize(VV.rows(),1);
+    std::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<VV.rows();v++) {
+        typename Kernel::FT p0,p1,p2;
+        assign_scalar(VV(v,0),p0);
+        assign_scalar(VV(v,1),p1);
+        assign_scalar(VV(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];
+    }
+}
+
+#ifdef IGL_STATIC_LIBRARY
+template void igl::copyleft::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::copyleft::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::copyleft::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::copyleft::cgal::remesh_intersections<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, CGAL::Epick, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -1, 0, -1, -1>, 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<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<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -1, 0, -1, -1> >&, 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> >&);
+template void igl::copyleft::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::copyleft::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::copyleft::cgal::remesh_intersections<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, CGAL::Epeck, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -1, 0, -1, -1>, 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&, 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<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -1, 0, -1, -1> >&, 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> >&);
+template void igl::copyleft::cgal::remesh_intersections<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, CGAL::Epick, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -1, 0, -1, -1>, 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&, 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<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -1, 0, -1, -1> >&, 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> >&);
+template void igl::copyleft::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::copyleft::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::copyleft::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::copyleft::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::copyleft::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::copyleft::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::copyleft::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> >&);
+template void igl::copyleft::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::copyleft::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::copyleft::cgal::remesh_intersections<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, CGAL::Epeck, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -1, 0, -1, -1>, 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<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<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -1, 0, -1, -1> >&, 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> >&);
+template void igl::copyleft::cgal::remesh_intersections<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, CGAL::Epick, 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::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<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -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::copyleft::cgal::remesh_intersections<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, CGAL::Epeck, 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::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<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -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> >&);
+#endif
+

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

@@ -0,0 +1,73 @@
+// 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_REMESH_INTERSECTIONS_H
+#define IGL_COPYLEFT_CGAL_REMESH_INTERSECTIONS_H
+
+#include "../../igl_inline.h"
+#include <Eigen/Dense>
+#include "CGAL_includes.hpp"
+
+namespace igl
+{
+  namespace copyleft
+  {
+    namespace cgal
+    {
+      // Remesh faces according to results of intersection detection and
+      // construction (e.g. from `igl::copyleft::cgal::intersect_other` or
+      // `igl::copyleft::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

+ 95 - 0
include/igl/copyleft/cgal/remesh_self_intersections.cpp

@@ -0,0 +1,95 @@
+// 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 "../../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::copyleft::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::copyleft::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::copyleft::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::copyleft::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::copyleft::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::copyleft::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::copyleft::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::copyleft::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::copyleft::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::copyleft::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::copyleft::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::copyleft::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::copyleft::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::copyleft::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::copyleft::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> >&);
+template void igl::copyleft::cgal::remesh_self_intersections<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, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, Eigen::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&, igl::copyleft::cgal::RemeshSelfIntersectionsParam const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -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<long, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
+template void igl::copyleft::cgal::remesh_self_intersections<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, Eigen::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::copyleft::cgal::RemeshSelfIntersectionsParam const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -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<long, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
+template void igl::copyleft::cgal::remesh_self_intersections<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -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::copyleft::cgal::RemeshSelfIntersectionsParam const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -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> >&);
+#endif

+ 88 - 0
include/igl/copyleft/cgal/remesh_self_intersections.h

@@ -0,0 +1,88 @@
+// 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_REMESH_SELF_INTERSECTIONS_H
+#define IGL_COPYLEFT_CGAL_REMESH_SELF_INTERSECTIONS_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
+    {
+      // 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::copyleft::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::copyleft::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

+ 9 - 10
include/igl/cgal/signed_distance_isosurface.cpp → include/igl/copyleft/cgal/signed_distance_isosurface.cpp

@@ -9,14 +9,13 @@
 #include "point_mesh_squared_distance.h"
 #include "complex_to_mesh.h"
 
-#include "../AABB.h"
-#include "../per_face_normals.h"
-#include "../per_edge_normals.h"
-#include "../per_vertex_normals.h"
-#include "../centroid.h"
-#include "../WindingNumberAABB.h"
-#include "../matlab_format.h"
-#include "../remove_unreferenced.h"
+#include "../../AABB.h"
+#include "../../per_face_normals.h"
+#include "../../per_edge_normals.h"
+#include "../../per_vertex_normals.h"
+#include "../../centroid.h"
+#include "../../WindingNumberAABB.h"
+#include "../../matlab_format.h"
 
 #include <CGAL/Surface_mesh_default_triangulation_3.h>
 #include <CGAL/Complex_2_in_triangulation_3.h>
@@ -29,7 +28,7 @@
 #include <CGAL/AABB_triangle_primitive.h>
 #include <vector>
 
-IGL_INLINE bool igl::cgal::signed_distance_isosurface(
+IGL_INLINE bool igl::copyleft::cgal::signed_distance_isosurface(
   const Eigen::MatrixXd & IV,
   const Eigen::MatrixXi & IF,
   const double level,
@@ -136,5 +135,5 @@ IGL_INLINE bool igl::cgal::signed_distance_isosurface(
   // meshing surface
   CGAL::make_surface_mesh(c2t3, surface, criteria, CGAL::Manifold_tag());
   // complex to (V,F)
-  return igl::cgal::complex_to_mesh(c2t3,V,F);
+  return igl::copyleft::cgal::complex_to_mesh(c2t3,V,F);
 }

+ 54 - 0
include/igl/copyleft/cgal/signed_distance_isosurface.h

@@ -0,0 +1,54 @@
+// 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_SIGNED_DISTANCE_ISOSURFACE_H
+#define IGL_COPYLEFT_CGAL_SIGNED_DISTANCE_ISOSURFACE_H
+#include "../../igl_inline.h"
+#include "../../signed_distance.h"
+#include <Eigen/Core>
+namespace igl
+{
+  namespace copyleft
+  {
+    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
+

+ 16 - 15
include/igl/marching_cubes.cpp → include/igl/copyleft/marching_cubes.cpp

@@ -27,9 +27,9 @@
 #include "marching_cubes_tables.h"
 #include <map>
 
-extern int edgeTable[256];
-extern int triTable[256][2][17];
-extern int polyTable[8][16];
+extern const int edgeTable[256];
+extern const int triTable[256][2][17];
+extern const int polyTable[8][16];
 
 class EdgeKey 
 {
@@ -220,13 +220,14 @@ public:
 
 
 template <typename DerivedV, typename DerivedF>
-IGL_INLINE void igl::marching_cubes(const Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 1> &values,
-                                    const Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 3> &points,
-                                    const unsigned x_res,
-                                    const unsigned y_res,
-                                    const unsigned z_res,
-                                    Eigen::PlainObjectBase<DerivedV> &vertices,
-                                    Eigen::PlainObjectBase<DerivedF> &faces)
+IGL_INLINE void igl::copyleft::marching_cubes(
+  const Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 1> &values,
+  const Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 3> &points,
+  const unsigned x_res,
+  const unsigned y_res,
+  const unsigned z_res,
+  Eigen::PlainObjectBase<DerivedV> &vertices,
+  Eigen::PlainObjectBase<DerivedF> &faces)
 {
   MarchingCubes<DerivedV, DerivedF> mc(values, 
                                        points, 
@@ -238,9 +239,9 @@ IGL_INLINE void igl::marching_cubes(const Eigen::Matrix<typename DerivedV::Scala
 }
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
-template void igl::marching_cubes<Eigen::Matrix<float, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(Eigen::Matrix<Eigen::Matrix<float, -1, 3, 0, -1, 3>::Scalar, -1, 1, 0, -1, 1> const&, Eigen::Matrix<Eigen::Matrix<float, -1, 3, 0, -1, 3>::Scalar, -1, 3, 0, -1, 3> const&, unsigned int, unsigned int, unsigned int, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);
-template void igl::marching_cubes<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(Eigen::Matrix<Eigen::Matrix<double, -1, 3, 0, -1, 3>::Scalar, -1, 1, 0, -1, 1> const&, Eigen::Matrix<Eigen::Matrix<double, -1, 3, 0, -1, 3>::Scalar, -1, 3, 0, -1, 3> const&, unsigned int, unsigned int, unsigned int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);
-template void igl::marching_cubes<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<unsigned int, -1, 3, 0, -1, 3> >(Eigen::Matrix<Eigen::Matrix<double, -1, 3, 0, -1, 3>::Scalar, -1, 1, 0, -1, 1> const&, Eigen::Matrix<Eigen::Matrix<double, -1, 3, 0, -1, 3>::Scalar, -1, 3, 0, -1, 3> const&, unsigned int, unsigned int, unsigned int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<unsigned int, -1, 3, 0, -1, 3> >&);
-template void igl::marching_cubes<Eigen::Matrix<float, -1, 3, 0, -1, 3>, Eigen::Matrix<unsigned int, -1, 3, 0, -1, 3> >(Eigen::Matrix<Eigen::Matrix<float, -1, 3, 0, -1, 3>::Scalar, -1, 1, 0, -1, 1> const&, Eigen::Matrix<Eigen::Matrix<float, -1, 3, 0, -1, 3>::Scalar, -1, 3, 0, -1, 3> const&, unsigned int, unsigned int, unsigned int, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<unsigned int, -1, 3, 0, -1, 3> >&);
-template void igl::marching_cubes<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::Matrix<Eigen::Matrix<double, -1, -1, 0, -1, -1>::Scalar, -1, 1, 0, -1, 1> const&, Eigen::Matrix<Eigen::Matrix<double, -1, -1, 0, -1, -1>::Scalar, -1, 3, 0, -1, 3> const&, unsigned int, unsigned int, unsigned int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+template void igl::copyleft::marching_cubes<Eigen::Matrix<float, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(Eigen::Matrix<Eigen::Matrix<float, -1, 3, 0, -1, 3>::Scalar, -1, 1, 0, -1, 1> const&, Eigen::Matrix<Eigen::Matrix<float, -1, 3, 0, -1, 3>::Scalar, -1, 3, 0, -1, 3> const&, unsigned int, unsigned int, unsigned int, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);
+template void igl::copyleft::marching_cubes<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(Eigen::Matrix<Eigen::Matrix<double, -1, 3, 0, -1, 3>::Scalar, -1, 1, 0, -1, 1> const&, Eigen::Matrix<Eigen::Matrix<double, -1, 3, 0, -1, 3>::Scalar, -1, 3, 0, -1, 3> const&, unsigned int, unsigned int, unsigned int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);
+template void igl::copyleft::marching_cubes<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<unsigned int, -1, 3, 0, -1, 3> >(Eigen::Matrix<Eigen::Matrix<double, -1, 3, 0, -1, 3>::Scalar, -1, 1, 0, -1, 1> const&, Eigen::Matrix<Eigen::Matrix<double, -1, 3, 0, -1, 3>::Scalar, -1, 3, 0, -1, 3> const&, unsigned int, unsigned int, unsigned int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<unsigned int, -1, 3, 0, -1, 3> >&);
+template void igl::copyleft::marching_cubes<Eigen::Matrix<float, -1, 3, 0, -1, 3>, Eigen::Matrix<unsigned int, -1, 3, 0, -1, 3> >(Eigen::Matrix<Eigen::Matrix<float, -1, 3, 0, -1, 3>::Scalar, -1, 1, 0, -1, 1> const&, Eigen::Matrix<Eigen::Matrix<float, -1, 3, 0, -1, 3>::Scalar, -1, 3, 0, -1, 3> const&, unsigned int, unsigned int, unsigned int, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<unsigned int, -1, 3, 0, -1, 3> >&);
+template void igl::copyleft::marching_cubes<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::Matrix<Eigen::Matrix<double, -1, -1, 0, -1, -1>::Scalar, -1, 1, 0, -1, 1> const&, Eigen::Matrix<Eigen::Matrix<double, -1, -1, 0, -1, -1>::Scalar, -1, 3, 0, -1, 3> const&, unsigned int, unsigned int, unsigned int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 #endif

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