Browse Source

booleans in tutorial

Former-commit-id: 7a8984f6aee752b7cd7aeffdcfe5b3b8a07b05fc
Alec Jacobson 10 years ago
parent
commit
df488db3b0

+ 10 - 7
include/igl/boolean/MeshBooleanType.h

@@ -1,14 +1,17 @@
 #ifndef MESH_BOOLEAN_TYPE_H
 #define MESH_BOOLEAN_TYPE_H
 
-enum MeshBooleanType
+namespace igl
 {
-  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
+  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

+ 1 - 0
include/igl/boolean/from_cork_mesh.cpp

@@ -31,6 +31,7 @@ IGL_INLINE void igl::from_cork_mesh(
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
 template void igl::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::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

+ 60 - 13
include/igl/boolean/mesh_boolean.cpp

@@ -5,6 +5,34 @@
 #include <igl/unique_simplices.h>
 #include <iostream>
 
+template <
+  typename DerivedVA,
+  typename DerivedFA,
+  typename DerivedVB,
+  typename DerivedFB,
+  typename DerivedVC,
+  typename DerivedFC,
+  typename DerivedJ>
+IGL_INLINE void igl::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)
+{
+  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>&)> 
+    empty_fun;
+  return mesh_boolean(VA,FA,VB,FB,type,empty_fun,VC,FC,J);
+}
+
 template <
   typename DerivedVA,
   typename DerivedFA,
@@ -21,13 +49,15 @@ IGL_INLINE void igl::mesh_boolean(
   Eigen::PlainObjectBase<DerivedVC > & VC,
   Eigen::PlainObjectBase<DerivedFC > & FC)
 {
+  Eigen::Matrix<typename DerivedFC::Index, Eigen::Dynamic,1> J;
   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::Scalar, Eigen::Dynamic,3>&, 
+          Eigen::Matrix<typename DerivedFC::Index, Eigen::Dynamic,1>&)> 
     empty_fun;
-  return mesh_boolean(VA,FA,VB,FB,type,empty_fun,VC,FC);
+  return mesh_boolean(VA,FA,VB,FB,type,empty_fun,VC,FC,J);
 }
 
 template <
@@ -36,7 +66,8 @@ template <
   typename DerivedVB,
   typename DerivedFB,
   typename DerivedVC,
-  typename DerivedFC>
+  typename DerivedFC,
+  typename DerivedJ>
 IGL_INLINE void igl::mesh_boolean(
   const Eigen::PlainObjectBase<DerivedVA > & VA,
   const Eigen::PlainObjectBase<DerivedFA > & FA,
@@ -47,10 +78,12 @@ IGL_INLINE void igl::mesh_boolean(
     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::Scalar, Eigen::Dynamic,3>&,
+          Eigen::Matrix<typename DerivedJ::Scalar, Eigen::Dynamic,1>&)> 
     & resolve_fun,
   Eigen::PlainObjectBase<DerivedVC > & VC,
-  Eigen::PlainObjectBase<DerivedFC > & FC)
+  Eigen::PlainObjectBase<DerivedFC > & FC,
+  Eigen::PlainObjectBase<DerivedJ > & J)
 {
   using namespace Eigen;
   using namespace std;
@@ -63,6 +96,7 @@ IGL_INLINE void igl::mesh_boolean(
   typedef Matrix<Index,Dynamic,3> MatrixX3I;
   typedef Matrix<Index,Dynamic,2> MatrixX2I;
   typedef Matrix<Index,Dynamic,1> VectorXI;
+  typedef Matrix<typename DerivedJ::Scalar,Dynamic,1> VectorXJ;
   MatrixX3S V(VA.rows()+VB.rows(),3);
   MatrixX3I F(FA.rows()+FB.rows(),3);
   V.block(0,0,VA.rows(),VA.cols()) = VA;
@@ -89,14 +123,15 @@ IGL_INLINE void igl::mesh_boolean(
     const MatrixX3S & V,
     const MatrixX3I & F,
     MatrixX3S & CV,
-    MatrixX3I & CF)
+    MatrixX3I & CF,
+    VectorXJ & J)
   {
     MatrixX3S SV;
     MatrixX3I SF;
     MatrixX2I SIF;
-    VectorXI SJ,SIM,UIM;
+    VectorXI SIM,UIM;
     RemeshSelfIntersectionsParam params;
-    remesh_self_intersections(V,F,params,SV,SF,SIF,SJ,SIM);
+    remesh_self_intersections(V,F,params,SV,SF,SIF,J,SIM);
     for_each(SF.data(),SF.data()+SF.size(),[&SIM](int & a){a=SIM(a);});
     {
       remove_unreferenced(SV,SF,CV,CF,UIM);
@@ -105,18 +140,20 @@ IGL_INLINE void igl::mesh_boolean(
 
   MatrixX3S CV;
   MatrixX3I CF;
+  VectorXJ CJ;
   if(resolve_fun)
   {
-    resolve_fun(V,F,CV,CF);
+    resolve_fun(V,F,CV,CF,CJ);
   }else
   {
-    libigl_resolve(V,F,CV,CF);
+    libigl_resolve(V,F,CV,CF,CJ);
   }
 
   if(type == MESH_BOOLEAN_TYPE_RESOLVE)
   {
     FC = CF;
     VC = CV;
+    J = CJ;
     return;
   }
 
@@ -152,7 +189,7 @@ IGL_INLINE void igl::mesh_boolean(
         if((!odd(f) && !flip(f)) || (odd(f) && flip(f)))
         {
           vG.push_back(f);
-          Gflip.push_back(false);
+          Gflip.push_back(type == MESH_BOOLEAN_TYPE_MINUS);
         }
         break;
       default:
@@ -162,14 +199,23 @@ IGL_INLINE void igl::mesh_boolean(
   }
   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]);
   }
   // remove duplicates: cancel out in all cases? assertion in others?
   {
     MatrixXi oldG = G;
-    unique_simplices(oldG,G);
+    VectorXi IA,_1;
+    unique_simplices(oldG,G,IA,_1);
+    assert(IA.rows() == G.rows());
+    J.resize(IA.rows(),1);
+    for(size_t j = 0;j<(size_t)J.size();j++)
+    {
+      J(j) = GJ(IA(j));
+    }
   }
   // remove unreferenced vertices
   VectorXi newIM;
@@ -181,5 +227,6 @@ IGL_INLINE void igl::mesh_boolean(
 
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
-template void igl::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&, 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::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::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::mesh_boolean<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, igl::MeshBooleanType const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 #endif

+ 25 - 4
include/igl/boolean/mesh_boolean.h

@@ -19,9 +19,27 @@ namespace igl
   //  Outputs:
   //    W  #W by 3 list of vertex positions of boolean result mesh
   //    H  #H by 3 list of triangle indices into W
+  //    J  #H list of indices into [FA;FB] revealing "birth" facet
   //  
   //  See also: self_intersect
   //     
+  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);
   template <
     typename DerivedVA,
     typename DerivedFA,
@@ -46,7 +64,8 @@ namespace igl
     typename DerivedVB,
     typename DerivedFB,
     typename DerivedVC,
-    typename DerivedFC>
+    typename DerivedFC,
+    typename DerivedJ>
   IGL_INLINE void mesh_boolean(
     const Eigen::PlainObjectBase<DerivedVA > & VA,
     const Eigen::PlainObjectBase<DerivedFA > & FA,
@@ -55,12 +74,14 @@ namespace igl
     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> &,
+      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::Scalar,Eigen::Dynamic,3> &,
+            Eigen::Matrix<typename  DerivedJ::Scalar,Eigen::Dynamic,1>&)> 
       & resolve_fun,
     Eigen::PlainObjectBase<DerivedVC > & VC,
-    Eigen::PlainObjectBase<DerivedFC > & FC);
+    Eigen::PlainObjectBase<DerivedFC > & FC,
+    Eigen::PlainObjectBase<DerivedJ > & J);
 }
 
 #ifndef IGL_STATIC_LIBRARY

+ 1 - 0
include/igl/boolean/mesh_boolean_cork.cpp

@@ -88,6 +88,7 @@ IGL_INLINE void igl::mesh_boolean_cork(
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
 template void igl::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::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::MeshBooleanType const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);
 #endif
 
 #endif

+ 1 - 0
include/igl/boolean/to_cork_mesh.cpp

@@ -33,5 +33,6 @@ IGL_INLINE void igl::to_cork_mesh(
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
 template void igl::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::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

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

@@ -84,4 +84,5 @@ IGL_INLINE void igl::remesh_self_intersections(
 // Explicit template specialization
 template void igl::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::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::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::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::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::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> >&);
 #endif

+ 1 - 0
include/igl/matlab/mexStream.h

@@ -32,6 +32,7 @@ namespace igl
 }
 
 // Implementation 
+#include <mex.h>
 inline std::streamsize igl::MexStream::xsputn(
   const char *s, 
   std::streamsize n) 

+ 1 - 0
include/igl/matlab/prepare_lhs.cpp

@@ -37,4 +37,5 @@ IGL_INLINE void igl::prepare_lhs_index(
 template void igl::prepare_lhs_index<Eigen::Matrix<double, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, mxArray_tag**);
 template void igl::prepare_lhs_index<Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, mxArray_tag**);
 template void igl::prepare_lhs_double<Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, mxArray_tag**);
+template void igl::prepare_lhs_index<Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, mxArray_tag**);
 #endif

+ 3 - 7
include/igl/triangle_triangle_adjacency.cpp

@@ -137,7 +137,6 @@ template <
   using namespace std;
   assert(F.cols() == 3 && "Faces must be triangles");
   // number of faces
-  const int m = F.rows();
   typedef typename DerivedF::Index Index;
   typedef Matrix<typename DerivedF::Scalar,Dynamic,2> MatrixX2I;
   typedef Matrix<typename DerivedF::Index,Dynamic,1> VectorXI;
@@ -166,7 +165,7 @@ template <
   using namespace Eigen;
   typedef typename DerivedE::Index Index;
   const size_t m = E.rows()/3;
-  assert(E.rows() == m*3 && "E should come from list of triangles.");
+  assert((size_t)E.rows() == m*3 && "E should come from list of triangles.");
   // E2E[i] --> {j,k,...} means face edge i corresponds to other faces edges j
   // and k
   TT.resize (m,vector<vector<TTIndex> >(3));
@@ -177,20 +176,17 @@ template <
 
   // No race conditions because TT*[f][c]'s are in bijection with e's
   // Minimum number of iterms per openmp thread
-  const size_t ne = E.rows();
+  //const size_t num_e = E.rows();
 # ifndef IGL_OMP_MIN_VALUE
 #   define IGL_OMP_MIN_VALUE 1000
 # endif
-# pragma omp parallel for if (ne>IGL_OMP_MIN_VALUE)
+# pragma omp parallel for if (m>IGL_OMP_MIN_VALUE)
   // Slightly better memory access than loop over E
   for(Index f = 0;f<(Index)m;f++)
   {
     for(Index c = 0;c<3;c++)
     {
       const Index e = f + m*c;
-      const Index i = E(e,0);
-      const Index j = E(e,1);
-      //const Index f = e%m;
       //const Index c = e/m;
       const vector<Index> & N = uE2E[EMAP(e)];
       for(const auto & ne : N)

+ 1 - 1
include/igl/unique_edge_map.cpp

@@ -29,7 +29,7 @@ IGL_INLINE void igl::unique_edge_map(
   uE2E.resize(uE.rows());
   // This does help a little
   for_each(uE2E.begin(),uE2E.end(),[](vector<uE2EType > & v){v.reserve(2);});
-  assert(EMAP.size() == ne);
+  assert((size_t)EMAP.size() == ne);
   for(uE2EType e = 0;e<(uE2EType)ne;e++)
   {
     uE2E[EMAP(e)].push_back(e);

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

@@ -911,7 +911,7 @@ namespace igl
     glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
     glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
     #endif
-    window = glfwCreateWindow(1280, 800, "IGL Viewer", NULL, NULL);
+    window = glfwCreateWindow(1280, 800, "libigl viewer", NULL, NULL);
     if (!window)
     {
       glfwTerminate();

+ 15 - 0
tutorial/609_Boolean/CMakeLists.txt

@@ -0,0 +1,15 @@
+cmake_minimum_required(VERSION 2.6)
+project(609_Boolean)
+
+find_package(CGAL REQUIRED)
+include(${CGAL_USE_FILE})
+
+# for some reason must come after cgal include
+include("../CMakeLists.shared")
+
+set(SOURCES
+${PROJECT_SOURCE_DIR}/main.cpp
+)
+
+add_executable(${PROJECT_NAME}_bin ${SOURCES} ${SHARED_SOURCES})
+target_link_libraries(${PROJECT_NAME}_bin ${SHARED_LIBRARIES} ${CGAL_LIBRARIES})

+ 94 - 0
tutorial/609_Boolean/main.cpp

@@ -0,0 +1,94 @@
+#include <igl/readOFF.h>
+#define IGL_NO_CORK
+#include <igl/boolean/mesh_boolean.h>
+#include <igl/viewer/Viewer.h>
+
+#include <Eigen/Core>
+#include <iostream>
+
+Eigen::MatrixXd VA,VB,VC;
+Eigen::VectorXi J;
+Eigen::MatrixXi FA,FB,FC;
+igl::MeshBooleanType boolean_type(igl::MESH_BOOLEAN_TYPE_UNION);
+
+const char * MESH_BOOLEAN_TYPE_NAMES[] = 
+{
+  "Union",
+  "Intersect",
+  "Minus",
+  "XOR",
+  "Resolve",
+};
+
+void update(igl::Viewer &viewer)
+{
+  igl::mesh_boolean(VA,FA,VB,FB,boolean_type,VC,FC,J);
+  Eigen::MatrixXd C(FC.rows(),3);
+  for(size_t f = 0;f<C.rows();f++)
+  {
+    if(J(f)<FA.rows())
+    {
+      C.row(f) = Eigen::RowVector3d(1,0,0);
+    }else
+    {
+      C.row(f) = Eigen::RowVector3d(0,1,0);
+    }
+  }
+  viewer.data.clear();
+  viewer.data.set_mesh(VC,FC);
+  viewer.data.set_colors(C);
+}
+
+bool key_down(igl::Viewer &viewer, unsigned char key, int mods)
+{
+  switch(key)
+  {
+    default:
+      return false;
+    case '.':
+      boolean_type = 
+        static_cast<igl::MeshBooleanType>(
+          (boolean_type+1)% igl::NUM_MESH_BOOLEAN_TYPES);
+      break;
+    case ',':
+      boolean_type = 
+        static_cast<igl::MeshBooleanType>(
+          (boolean_type+igl::NUM_MESH_BOOLEAN_TYPES-1)%
+          igl::NUM_MESH_BOOLEAN_TYPES);
+      break;
+    case '[':
+      viewer.core.camera_dnear -= 0.1;
+      return true;
+    case ']':
+      viewer.core.camera_dnear += 0.1;
+      return true;
+  }
+  std::cout<<"A "<<MESH_BOOLEAN_TYPE_NAMES[boolean_type]<<" B."<<std::endl;
+  igl::mesh_boolean(VA,FA,VB,FB,boolean_type,VC,FC);
+  update(viewer);
+  return true;
+}
+
+int main(int argc, char *argv[])
+{
+  using namespace Eigen;
+  using namespace std;
+  igl::readOFF("../shared/cheburashka.off",VA,FA);
+  igl::readOFF("../shared/decimated-knight.off",VB,FB);
+  // Plot the mesh with pseudocolors
+  igl::Viewer viewer;
+
+  // Initialize
+  update(viewer);
+
+  viewer.core.show_lines = true;
+  viewer.callback_key_down = &key_down;
+  viewer.core.camera_dnear = 3.9;
+  cout<<
+    "Press '.' to switch to next boolean operation type."<<endl<<
+    "Press ',' to switch to previous boolean operation type."<<endl<<
+    "Press ']' to push near cutting plane away from camera."<<endl<<
+    "Press '[' to pull near cutting plane closer to camera."<<endl<<
+    "Hint: investigate _inside_ the model to see orientation changes."<<endl;
+  viewer.launch();
+}

+ 4 - 0
tutorial/CMakeLists.txt

@@ -12,6 +12,7 @@ find_package(MATLAB QUIET)
 
 ## Check for EMBREE, if not available skip the examples that depends on it
 find_package(EMBREE QUIET)
+find_package(CGAL QUIET)
 
 # Chapter 1
 add_subdirectory("101_FileIO")
@@ -68,3 +69,6 @@ add_subdirectory("606_AmbientOcclusion")
 add_subdirectory("607_Picking")
 endif(EMBREE_FOUND)
 add_subdirectory("608_LIM")
+if(CGAL_FOUND)
+add_subdirectory("609_Boolean")
+endif()

+ 92 - 0
tutorial/cmake/FindCGAL.cmake

@@ -0,0 +1,92 @@
+#
+# The following module is based on FindVTK.cmake
+#
+
+# - Find a CGAL installation or binary tree.
+# The following variables are set if CGAL is found.  If CGAL is not
+# found, CGAL_FOUND is set to false.
+#
+#  CGAL_FOUND         - Set to true when CGAL is found.
+#  CGAL_USE_FILE      - CMake file to use CGAL.
+#
+
+# Construct consitent error messages for use below.
+set(CGAL_DIR_DESCRIPTION "directory containing CGALConfig.cmake. This is either the binary directory where CGAL was configured or PREFIX/lib/CGAL for an installation.")
+set(CGAL_DIR_MESSAGE     "CGAL not found.  Set the CGAL_DIR cmake variable or environment variable to the ${CGAL_DIR_DESCRIPTION}")
+ 
+set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true)
+ 
+if ( NOT CGAL_DIR )
+  
+  # Get the system search path as a list.
+  if(UNIX)
+    string(REGEX MATCHALL "[^:]+" CGAL_DIR_SEARCH1 "$ENV{PATH}")
+  else()
+    string(REGEX REPLACE "\\\\" "/" CGAL_DIR_SEARCH1 "$ENV{PATH}")
+  endif()
+  
+  string(REGEX REPLACE "/;" ";" CGAL_DIR_SEARCH2 "${CGAL_DIR_SEARCH1}")
+
+  # Construct a set of paths relative to the system search path.
+  set(CGAL_DIR_SEARCH "")
+  
+  foreach(dir ${CGAL_DIR_SEARCH2})
+  
+    set(CGAL_DIR_SEARCH ${CGAL_DIR_SEARCH} ${dir}/../lib/CGAL )
+      
+  endforeach()
+
+
+  #
+  # Look for an installation or build tree.
+  #
+  find_path(CGAL_DIR CGALConfig.cmake
+
+    # Look for an environment variable CGAL_DIR.
+    $ENV{CGAL_DIR}
+
+    # Look in places relative to the system executable search path.
+    ${CGAL_DIR_SEARCH}
+
+    # Look in standard UNIX install locations.
+    /opt/local/share/CGAL/cmake
+    /usr/local/lib/CGAL
+    /usr/lib/CGAL
+
+    # Read from the CMakeSetup registry entries.  It is likely that
+    # CGAL will have been recently built.
+    [HKEY_CURRENT_USER\\Software\\Kitware\\CMakeSetup\\Settings\\StartPath;WhereBuild1]
+    [HKEY_CURRENT_USER\\Software\\Kitware\\CMakeSetup\\Settings\\StartPath;WhereBuild2]
+    [HKEY_CURRENT_USER\\Software\\Kitware\\CMakeSetup\\Settings\\StartPath;WhereBuild3]
+    [HKEY_CURRENT_USER\\Software\\Kitware\\CMakeSetup\\Settings\\StartPath;WhereBuild4]
+    [HKEY_CURRENT_USER\\Software\\Kitware\\CMakeSetup\\Settings\\StartPath;WhereBuild5]
+    [HKEY_CURRENT_USER\\Software\\Kitware\\CMakeSetup\\Settings\\StartPath;WhereBuild6]
+    [HKEY_CURRENT_USER\\Software\\Kitware\\CMakeSetup\\Settings\\StartPath;WhereBuild7]
+    [HKEY_CURRENT_USER\\Software\\Kitware\\CMakeSetup\\Settings\\StartPath;WhereBuild8]
+    [HKEY_CURRENT_USER\\Software\\Kitware\\CMakeSetup\\Settings\\StartPath;WhereBuild9]
+    [HKEY_CURRENT_USER\\Software\\Kitware\\CMakeSetup\\Settings\\StartPath;WhereBuild10]
+
+    # Help the user find it if we cannot.
+    DOC "The ${CGAL_DIR_DESCRIPTION}"
+  )
+  
+endif()
+
+if ( CGAL_DIR )
+  
+  if ( EXISTS "${CGAL_DIR}/CGALConfig.cmake" )
+    include( "${CGAL_DIR}/CGALConfig.cmake" )
+    set( CGAL_FOUND TRUE )
+  endif()
+
+endif()
+
+if( NOT CGAL_FOUND)
+  if(CGAL_FIND_REQUIRED)
+    MESSAGE(FATAL_ERROR ${CGAL_DIR_MESSAGE})
+  else()
+    if(NOT CGAL_FIND_QUIETLY)
+      MESSAGE(STATUS ${CGAL_DIR_MESSAGE})
+    endif()
+  endif()
+endif()

+ 14 - 0
tutorial/cmake/FindLIBIGL.cmake

@@ -73,6 +73,20 @@ if(LIBIGL_USE_STATIC_LIBRARY)
     message(FATAL_ERROR "could NOT find mosek")
   endif(MOSEK_FOUND)
 
+  FIND_LIBRARY( LIBIGLCGAL_LIBRARY NAMES iglcgal PATHS ${LIBIGL_LIB_DIRS})
+  if(NOT LIBIGLCGAL_LIBRARY)
+    set(LIBIGL_FOUND FALSE)
+    message(FATAL_ERROR "could NOT find libiglcgal")
+  endif(NOT LIBIGLCGAL_LIBRARY)
+  set(LIBIGL_LIBRARIES ${LIBIGL_LIBRARIES}  ${LIBIGLCGAL_LIBRARY})
+
+  FIND_LIBRARY( LIBIGLBOOLEAN_LIBRARY NAMES iglboolean PATHS ${LIBIGL_LIB_DIRS})
+  if(NOT LIBIGLBOOLEAN_LIBRARY)
+    set(LIBIGL_FOUND FALSE)
+    message(FATAL_ERROR "could NOT find libiglboolean ")
+  endif(NOT LIBIGLBOOLEAN_LIBRARY)
+  set(LIBIGL_LIBRARIES ${LIBIGL_LIBRARIES}  ${LIBIGLBOOLEAN_LIBRARY})
+
   FIND_LIBRARY( LIBIGLEMBREE_LIBRARY NAMES iglembree PATHS ${LIBIGL_LIB_DIRS})
   if(NOT LIBIGLEMBREE_LIBRARY)
     set(LIBIGL_FOUND FALSE)

+ 1 - 0
tutorial/images/cheburashka-knight-boolean.jpg.REMOVED.git-id

@@ -0,0 +1 @@
+687b6cd2769b89898267be8a92eb47e1fe599c02

+ 1 - 1
tutorial/tutorial.html.REMOVED.git-id

@@ -1 +1 @@
-141eb93f575045ab7a950e5674b54ec2fa87b197
+f2602624b7bcb67987e734aa2aa314ee093f8446

+ 1 - 1
tutorial/tutorial.md.REMOVED.git-id

@@ -1 +1 @@
-d0833fffecc624061e2d057e37e4e3e99cc11351
+b2cc83ba2762e50399cba9416676bd4d3146ad24