Browse Source

variadic booleans abstracted for matlab interface

Former-commit-id: 2102d77a2d5eaa4419552da4aedbf4d4b3cce539
Alec Jacobson 9 years ago
parent
commit
41096114f7

+ 41 - 9
include/igl/copyleft/cgal/BinaryWindingNumberOperations.h

@@ -18,6 +18,8 @@
 // function handles.
 //
 // Why is this templated on DerivedW
+//
+// These are all generalized to n-ary operations
 namespace igl
 {
   namespace copyleft
@@ -34,44 +36,74 @@ namespace igl
             }
       };
 
+      // A ∪ B ∪ ... ∪ Z
       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;
+              const Eigen::PlainObjectBase<DerivedW>& win_nums) const 
+          {
+            for(int i = 0;i<win_nums.size();i++)
+            {
+              if(win_nums(i) > 0) return true;
+            }
+            return false;
           }
       };
 
+      // A ∩ B ∩ ... ∩ Z
       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;
+              const Eigen::PlainObjectBase<DerivedW>& win_nums) const 
+          {
+            for(int i = 0;i<win_nums.size();i++)
+            {
+              if(win_nums(i)<=0) return false;
+            }
+            return true;
           }
       };
 
+      // A \ B \ ... \ Z = A \ (B ∪ ... ∪ Z)
       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;
+              const Eigen::PlainObjectBase<DerivedW>& win_nums) const 
+          {
+            assert(win_nums.size()>1);
+            // Union of objects 1 through n-1
+            bool union_rest = false;
+            for(int i = 1;i<win_nums.size();i++)
+            {
+              union_rest = union_rest || win_nums(i) > 0;
+              if(union_rest) break;
+            }
+            // Must be in object 0 and not in union of objects 1 through n-1
+            return win_nums(0) > 0 && !union_rest;
           }
       };
 
+      // A ∆ B ∆ ... ∆ Z  (equivalent to set inside odd number of objects)
       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);
+              const Eigen::PlainObjectBase<DerivedW>& win_nums) const 
+          {
+            // If inside an odd number of objects
+            int count = 0;
+            for(int i = 0;i<win_nums.size();i++)
+            {
+              if(win_nums(i) > 0) count++;
+            }
+            return count % 2 == 1;
           }
       };
 

+ 8 - 31
include/igl/copyleft/cgal/mesh_boolean.cpp

@@ -8,13 +8,13 @@
 // obtain one at http://mozilla.org/MPL/2.0/.
 //
 #include "mesh_boolean.h"
-#include "BinaryWindingNumberOperations.h"
 #include "assign_scalar.h"
-#include "string_to_mesh_boolean_type.h"
+#include "extract_cells.h"
+#include "mesh_boolean_type_to_funcs.h"
 #include "propagate_winding_numbers.h"
-#include "remesh_self_intersections.h"
 #include "relabel_small_immersed_cells.h"
-#include "extract_cells.h"
+#include "remesh_self_intersections.h"
+#include "string_to_mesh_boolean_type.h"
 #include "../../cumsum.h"
 #include "../../extract_manifold_patches.h"
 #include "../../get_seconds.h"
@@ -49,33 +49,10 @@ IGL_INLINE bool igl::copyleft::cgal::mesh_boolean(
     Eigen::PlainObjectBase<DerivedFC > & FC,
     Eigen::PlainObjectBase<DerivedJ > & J)
 {
-  switch (type) 
-  {
-    case MESH_BOOLEAN_TYPE_UNION:
-      return igl::copyleft::cgal::mesh_boolean(
-          VA, FA, VB, FB, igl::copyleft::cgal::BinaryUnion(),
-          igl::copyleft::cgal::KeepInside(), VC, FC, J);
-    case MESH_BOOLEAN_TYPE_INTERSECT:
-      return igl::copyleft::cgal::mesh_boolean(
-          VA, FA, VB, FB, igl::copyleft::cgal::BinaryIntersect(),
-          igl::copyleft::cgal::KeepInside(), VC, FC, J);
-    case MESH_BOOLEAN_TYPE_MINUS:
-      return igl::copyleft::cgal::mesh_boolean(
-          VA, FA, VB, FB, igl::copyleft::cgal::BinaryMinus(),
-          igl::copyleft::cgal::KeepInside(), VC, FC, J);
-    case MESH_BOOLEAN_TYPE_XOR:
-      return igl::copyleft::cgal::mesh_boolean(
-          VA, FA, VB, FB, igl::copyleft::cgal::BinaryXor(),
-          igl::copyleft::cgal::KeepInside(), VC, FC, J);
-    case MESH_BOOLEAN_TYPE_RESOLVE:
-      //op = binary_resolve();
-      return igl::copyleft::cgal::mesh_boolean(
-          VA, FA, VB, FB, igl::copyleft::cgal::BinaryResolve(),
-          igl::copyleft::cgal::KeepAll(), VC, FC, J);
-    default:
-      assert(false && "Unsupported boolean type.");
-      return false;
-  }
+  std::function<int(const int, const int)> keep;
+  std::function<int(const Eigen::Matrix<int,1,Eigen::Dynamic>) > wind_num_op;
+  mesh_boolean_type_to_funcs(type,wind_num_op,keep);
+  return mesh_boolean(VA,FA,VB,FB,wind_num_op,keep,VC,FC,J);
 }
 template <
   typename DerivedVA,

+ 39 - 0
include/igl/copyleft/cgal/mesh_boolean_type_to_funcs.cpp

@@ -0,0 +1,39 @@
+#include "mesh_boolean_type_to_funcs.h"
+#include "BinaryWindingNumberOperations.h"
+
+IGL_INLINE void igl::copyleft::cgal::mesh_boolean_type_to_funcs(
+  const MeshBooleanType & type,
+  std::function<int(const Eigen::Matrix<int,1,Eigen::Dynamic>) >& wind_num_op,
+  std::function<int(const int, const int)> & keep)
+{
+  switch (type) 
+  {
+    case MESH_BOOLEAN_TYPE_UNION:
+      wind_num_op = BinaryUnion();
+      keep = KeepInside();
+      return;
+    case MESH_BOOLEAN_TYPE_INTERSECT:
+      wind_num_op = BinaryIntersect();
+      keep = KeepInside();
+      return;
+    case MESH_BOOLEAN_TYPE_MINUS:
+      wind_num_op = BinaryMinus();
+      keep = KeepInside();
+      return;
+    case MESH_BOOLEAN_TYPE_XOR:
+      wind_num_op = BinaryXor();
+      keep = KeepInside();
+      return;
+    case MESH_BOOLEAN_TYPE_RESOLVE:
+      wind_num_op = BinaryResolve();
+      keep = KeepAll();
+      return;
+    default:
+      assert(false && "Unsupported boolean type.");
+      return;
+  }
+}
+
+#ifdef IGL_STATIC_LIBRARY
+// Explicit template specialization
+#endif

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

@@ -0,0 +1,37 @@
+#ifndef IGL_COPYLEFT_CGAL_MESH_BOOLEAN_TYPE_TO_FUNCS_H
+#define IGL_COPYLEFT_CGAL_MESH_BOOLEAN_TYPE_TO_FUNCS_H
+
+#include "../../igl_inline.h"
+#include "../../MeshBooleanType.h"
+#include <Eigen/Core>
+#include <functional>
+namespace igl
+{
+  namespace copyleft
+  {
+    namespace cgal
+    {
+      // Convert a MeshBooleanType enum to a pair of winding number conversion
+      // function and "keep" function used by mesh_boolean
+      //
+      // Inputs:
+      //   type  MeshBooleanType enum value
+      // Outputs:
+      //    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
+      //
+      // See also: string_to_mesh_boolean_type
+      IGL_INLINE void mesh_boolean_type_to_funcs(
+        const MeshBooleanType & type,
+        std::function<int(const Eigen::Matrix<int,1,Eigen::Dynamic>) >& 
+          wind_num_op,
+        std::function<int(const int, const int)> & keep);
+    }
+  }
+}
+#ifndef IGL_STATIC_LIBRARY
+#  include "mesh_boolean_type_to_funcs.cpp"
+#endif
+#endif

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

@@ -11,13 +11,6 @@
 #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
 {

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

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

+ 7 - 0
include/igl/matlab/validate_arg.cpp

@@ -41,3 +41,10 @@ IGL_INLINE void igl::matlab::validate_arg_double(
   mexErrMsgTxt(mxIsDouble(prhs[i+1]),
     C_STR("Parameter '"<<name<<"' requires double argument"));
 }
+IGL_INLINE void igl::matlab::validate_arg_function_handle(
+    const int i, const int nrhs, const mxArray * prhs[], const char * name)
+{
+  requires_arg(i,nrhs,name);
+  mexErrMsgTxt(mxIsClass(prhs[i+1],"function_handle"),
+    C_STR("Parameter '"<<name<<"' requires function handle argument"));
+}

+ 2 - 0
include/igl/matlab/validate_arg.h

@@ -28,6 +28,8 @@ namespace igl
       const int i, const int nrhs, const mxArray * prhs[], const char * name);
     IGL_INLINE void validate_arg_double(
       const int i, const int nrhs, const mxArray * prhs[], const char * name);
+    IGL_INLINE void validate_arg_function_handle(
+      const int i, const int nrhs, const mxArray * prhs[], const char * name);
   }
 }
 #ifndef IGL_STATIC_LIBRARY