Browse Source

Added tutorial 609_Boolean and CGAL python module + functions

Former-commit-id: 7b6b91bd7abfe2f77a2866b0f06fe4beb445e3df
Sebastian Koch 9 years ago
parent
commit
9727746942

+ 5 - 0
python/CMakeLists.txt

@@ -107,6 +107,11 @@ if (LIBIGL_WITH_TRIANGLE)
   list(APPEND SHARED_SOURCES "modules/py_igl_triangle.cpp")
 endif ()
 
+if (LIBIGL_WITH_CGAL)
+  add_definitions(-DPY_CGAL)
+  list(APPEND SHARED_SOURCES "modules/copyleft/py_igl_cgal.cpp")
+endif ()
+
 
 ## Prepare the python library
 add_library(pyigl SHARED

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

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

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

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

+ 10 - 0
python/py_igl/py_MeshBooleanType.cpp

@@ -0,0 +1,10 @@
+py::enum_<igl::MeshBooleanType>(m, "MeshBooleanType")
+    .value("MESH_BOOLEAN_TYPE_UNION", igl::MESH_BOOLEAN_TYPE_UNION)
+    .value("MESH_BOOLEAN_TYPE_INTERSECT", igl::MESH_BOOLEAN_TYPE_INTERSECT)
+    .value("MESH_BOOLEAN_TYPE_MINUS", igl::MESH_BOOLEAN_TYPE_MINUS)
+    .value("MESH_BOOLEAN_TYPE_XOR", igl::MESH_BOOLEAN_TYPE_XOR)
+    .value("MESH_BOOLEAN_TYPE_RESOLVE", igl::MESH_BOOLEAN_TYPE_RESOLVE)
+    .value("NUM_MESH_BOOLEAN_TYPES", igl::NUM_MESH_BOOLEAN_TYPES)
+    .export_values();
+
+

+ 79 - 0
python/python_shared.cpp

@@ -26,6 +26,10 @@ extern void python_export_igl_embree(py::module &);
 extern void python_export_igl_triangle(py::module &);
 #endif
 
+#ifdef PY_CGAL
+extern void python_export_igl_cgal(py::module &);
+#endif
+
 PYBIND11_PLUGIN(pyigl) {
     py::module m("pyigl", R"pyigldoc(
         Python wrappers for libigl
@@ -36,6 +40,77 @@ PYBIND11_PLUGIN(pyigl) {
         .. autosummary::
            :toctree: _generate
 
+           AABB
+           ARAPEnergyType
+           MeshBooleanType
+           SolverStatus
+           active_set
+           arap
+           avg_edge_length
+           barycenter
+           barycentric_coordinates
+           boundary_facets
+           boundary_loop
+           cat
+           colon
+           comb_cross_field
+           comb_frame_field
+           compute_frame_field_bisectors
+           copyleft_cgal_mesh_boolean
+           copyleft_comiso_miq
+           copyleft_comiso_nrosy
+           copyleft_tetgen_tetrahedralize
+           cotmatrix
+           covariance_scatter_matrix
+           cross_field_missmatch
+           cut_mesh_from_singularities
+           doublearea
+           edge_lengths
+           eigs
+           embree_ambient_occlusion
+           find_cross_field_singularities
+           fit_rotations
+           floor
+           gaussian_curvature
+           grad
+           harmonic
+           invert_diag
+           jet
+           local_basis
+           lscm
+           map_vertices_to_circle
+           massmatrix
+           min_quad_with_fixed
+           n_polyvector
+           parula
+           per_corner_normals
+           per_edge_normals
+           per_face_normals
+           per_vertex_normals
+           planarize_quad_mesh
+           point_mesh_squared_distance
+           polar_svd
+           principal_curvature
+           quad_planarity
+           readDMAT
+           readMESH
+           readOBJ
+           readOFF
+           read_triangle_mesh
+           rotate_vectors
+           setdiff
+           signed_distance
+           slice
+           slice_into
+           slice_mask
+           slice_tets
+           sortrows
+           triangle_triangulate
+           unique
+           unproject_onto_mesh
+           upsample
+           writeMESH
+           writeOBJ
 
     )pyigldoc");
 
@@ -63,5 +138,9 @@ PYBIND11_PLUGIN(pyigl) {
     python_export_igl_triangle(m);
     #endif
 
+    #ifdef PY_CGAL
+    python_export_igl_cgal(m);
+    #endif
+
     return m.ptr();
 }

+ 8 - 0
python/scripts/python_shared.mako

@@ -26,6 +26,10 @@ extern void python_export_igl_embree(py::module &);
 extern void python_export_igl_triangle(py::module &);
 #endif
 
+#ifdef PY_CGAL
+extern void python_export_igl_cgal(py::module &);
+#endif
+
 PYBIND11_PLUGIN(pyigl) {
     py::module m("pyigl", R"pyigldoc(
         Python wrappers for libigl
@@ -66,5 +70,9 @@ PYBIND11_PLUGIN(pyigl) {
     python_export_igl_triangle(m);
     #endif
 
+    #ifdef PY_CGAL
+    python_export_igl_cgal(m);
+    #endif
+
     return m.ptr();
 }

+ 84 - 0
python/tutorial/609_Boolean.py

@@ -0,0 +1,84 @@
+import sys, os
+
+# Add the igl library to the modules search path
+sys.path.insert(0, os.getcwd() + "/../")
+import pyigl as igl
+
+from shared import TUTORIAL_SHARED_PATH, check_dependencies
+
+dependencies = ["cgal", "viewer"]
+check_dependencies(dependencies)
+
+boolean_type_names = {igl.MESH_BOOLEAN_TYPE_UNION: "Union", igl.MESH_BOOLEAN_TYPE_INTERSECT: "Intersect", igl.MESH_BOOLEAN_TYPE_MINUS: "Minus", igl.MESH_BOOLEAN_TYPE_XOR: "XOR", igl.MESH_BOOLEAN_TYPE_RESOLVE: "Resolve"}
+
+boolean_types = list(boolean_type_names.keys())
+
+
+
+
+def update(viewer):
+    print("Calculating A %s B..." % boolean_type_names[boolean_type])
+    igl.cgal.mesh_boolean(VA, FA, VB, FB, boolean_type, VC, FC, J)
+    C = igl.eigen.MatrixXd(FC.rows(), 3)
+
+    for f in range(C.rows()):
+        if J[f] < FA.rows():
+            C.setRow(f, Red)
+        else:
+            C.setRow(f, Green)
+
+    viewer.data.clear()
+    viewer.data.set_mesh(VC, FC)
+    viewer.data.set_colors(C)
+    print("Done.")
+
+
+def key_down(viewer, key, modifier):
+    global boolean_type
+    # print(boolean_types)
+    if key == ord('.'):
+        boolean_type = boolean_types[(boolean_types.index(boolean_type) + 1) % (len(boolean_types))]
+    elif key == ord(','):
+        boolean_type = boolean_types[(boolean_types.index(boolean_type) + len(boolean_types) - 1) % len(boolean_types)]
+    elif key == ord('['):
+        viewer.core.camera_dnear -= 0.1
+    elif key == ord(']'):
+        viewer.core.camera_dnear += 0.1
+    else:
+        return False
+
+    #igl.cgal.mesh_boolean(VA, FA, VB, FB, boolean_type, VC, FC)
+    update(viewer)
+
+    return False
+
+
+if __name__ == "__main__":
+    # Mesh with per-face color
+    VA = igl.eigen.MatrixXd()
+    FA = igl.eigen.MatrixXi()
+    VB = igl.eigen.MatrixXd()
+    FB = igl.eigen.MatrixXi()
+    VC = igl.eigen.MatrixXd()
+    FC = igl.eigen.MatrixXi()
+    J = igl.eigen.MatrixXi()
+
+    Red = igl.eigen.MatrixXd([[1, 0, 0]])
+    Green = igl.eigen.MatrixXd([[0, 1, 0]])
+
+    # Load meshes in OFF format
+    igl.readOFF(TUTORIAL_SHARED_PATH + "cheburashka.off", VA, FA)
+    igl.readOFF(TUTORIAL_SHARED_PATH + "decimated-knight.off", VB, FB)
+
+    boolean_type = igl.MESH_BOOLEAN_TYPE_UNION
+
+    viewer = igl.viewer.Viewer()
+    update(viewer)
+
+    print(
+        "Usage: Press '.' to switch to next boolean operation type. \nPress ',' to switch to previous boolean operation type. \nPress ']' to push near cutting plane away from camera. \nPress '[' to pull near cutting plane closer to camera. \nHint: investigate _inside_ the model to see orientation changes. \n")
+
+    viewer.core.show_lines = True
+    viewer.callback_key_down = key_down
+    viewer.core.camera_dnear = 3.9
+    viewer.launch()

+ 1 - 2
tutorial/609_Boolean/main.cpp

@@ -41,6 +41,7 @@ void update(igl::viewer::Viewer &viewer)
   viewer.data.clear();
   viewer.data.set_mesh(VC,FC);
   viewer.data.set_colors(C);
+  std::cout<<"A "<<MESH_BOOLEAN_TYPE_NAMES[boolean_type]<<" B."<<std::endl;
 }
 
 bool key_down(igl::viewer::Viewer &viewer, unsigned char key, int mods)
@@ -67,8 +68,6 @@ bool key_down(igl::viewer::Viewer &viewer, unsigned char key, int mods)
       viewer.core.camera_dnear += 0.1;
       return true;
   }
-  std::cout<<"A "<<MESH_BOOLEAN_TYPE_NAMES[boolean_type]<<" B."<<std::endl;
-  igl::copyleft::cgal::mesh_boolean(VA,FA,VB,FB,boolean_type,VC,FC);
   update(viewer);
   return true;
 }