Browse Source

Added tutorial 706

Former-commit-id: 3acc7106d45eb6773da422f6cf071d306bd035de
Sebastian Koch 9 years ago
parent
commit
70f5ed2048

+ 2 - 0
python/modules/py_igl_embree.cpp

@@ -6,6 +6,7 @@
 #include "../python_shared.h"
 
 #include <igl/embree/ambient_occlusion.h>
+#include <igl/embree/reorient_facets_raycast.h>
 
 
 void python_export_igl_embree(py::module &me) {
@@ -14,5 +15,6 @@ void python_export_igl_embree(py::module &me) {
     "embree", "Wrappers for libigl functions that use embree");
 
   #include "../py_igl/embree/py_ambient_occlusion.cpp"
+  #include "../py_igl/embree/py_reorient_facets_raycast.cpp"
 
 }

+ 33 - 0
python/py_doc.cpp

@@ -380,6 +380,23 @@ const char *__doc_igl_embree_ambient_occlusion = R"igl_Qu8mg5v7(// Compute ambie
     //    S  #P list of ambient occlusion values between 1 (fully occluded) and
     //      0 (not occluded)
     //)igl_Qu8mg5v7";
+const char *__doc_igl_embree_reorient_facets_raycast = R"igl_Qu8mg5v7(// Orient each component (identified by C) of a mesh (V,F) using ambient
+    // occlusion such that the front side is less occluded than back side, as
+    // described in "A Simple Method for Correcting Facet Orientations in
+    // Polygon Meshes Based on Ray Casting" [Takayama et al. 2014].
+    //
+    // Inputs:
+    //   V  #V by 3 list of vertex positions
+    //   F  #F by 3 list of triangle indices
+    //   rays_total  Total number of rays that will be shot
+    //   rays_minimum  Minimum number of rays that each patch should receive
+    //   facet_wise  Decision made for each face independently, no use of patches
+    //     (i.e., each face is treated as a patch)
+    //   use_parity  Use parity mode
+    //   is_verbose  Verbose output to cout
+    // Outputs:
+    //   I  #F list of whether face has been flipped
+    //   C  #F list of patch ID (output of bfs_orient > manifold patches))igl_Qu8mg5v7";
 const char *__doc_igl_find_cross_field_singularities = R"igl_Qu8mg5v7(// Inputs:
   //   V                #V by 3 eigen Matrix of mesh vertex 3D positions
   //   F                #F by 3 eigen Matrix of face (quad) indices
@@ -446,6 +463,16 @@ const char *__doc_igl_harmonic = R"igl_Qu8mg5v7(// Compute k-harmonic weight fun
   // Outputs:
   //   W  #V by #W list of weights
   //)igl_Qu8mg5v7";
+const char *__doc_igl_hsv_to_rgb = R"igl_Qu8mg5v7(// Convert RGB to HSV
+  //
+  // Inputs:
+  //   h  hue value (degrees: [0,360])
+  //   s  saturation value ([0,1])
+  //   v  value value ([0,1])
+  // Outputs:
+  //   r  red value ([0,1]) 
+  //   g  green value ([0,1])
+  //   b  blue value ([0,1]))igl_Qu8mg5v7";
 const char *__doc_igl_internal_angles = R"igl_Qu8mg5v7(// Compute internal angles for a triangle mesh
   //
   // Inputs:
@@ -738,6 +765,12 @@ const char *__doc_igl_quad_planarity = R"igl_Qu8mg5v7(// Compute planarity of th
   // Output:
   //   P  #F by 1 eigen Matrix of mesh face (quad) planarities
   //)igl_Qu8mg5v7";
+const char *__doc_igl_randperm = R"igl_Qu8mg5v7(// Like matlab's randperm(n) but minus 1
+  //
+  // Inputs:
+  //   n  number of elements
+  // Outputs:
+  //   I  n list of rand permutation of 0:n-1)igl_Qu8mg5v7";
 const char *__doc_igl_readDMAT = R"igl_Qu8mg5v7(See readDMAT for the documentation.)igl_Qu8mg5v7";
 const char *__doc_igl_readMESH = R"igl_Qu8mg5v7(// load a tetrahedral volume mesh from a .mesh file
   //

+ 3 - 0
python/py_doc.h

@@ -27,6 +27,7 @@ extern const char *__doc_igl_doublearea_quad;
 extern const char *__doc_igl_edge_lengths;
 extern const char *__doc_igl_eigs;
 extern const char *__doc_igl_embree_ambient_occlusion;
+extern const char *__doc_igl_embree_reorient_facets_raycast;
 extern const char *__doc_igl_find_cross_field_singularities;
 extern const char *__doc_igl_fit_rotations;
 extern const char *__doc_igl_fit_rotations_planar;
@@ -35,6 +36,7 @@ extern const char *__doc_igl_floor;
 extern const char *__doc_igl_gaussian_curvature;
 extern const char *__doc_igl_grad;
 extern const char *__doc_igl_harmonic;
+extern const char *__doc_igl_hsv_to_rgb;
 extern const char *__doc_igl_internal_angles;
 extern const char *__doc_igl_invert_diag;
 extern const char *__doc_igl_is_irregular_vertex;
@@ -60,6 +62,7 @@ extern const char *__doc_igl_point_mesh_squared_distance;
 extern const char *__doc_igl_polar_svd;
 extern const char *__doc_igl_principal_curvature;
 extern const char *__doc_igl_quad_planarity;
+extern const char *__doc_igl_randperm;
 extern const char *__doc_igl_readDMAT;
 extern const char *__doc_igl_readMESH;
 extern const char *__doc_igl_readOBJ;

+ 4 - 0
python/py_igl.cpp

@@ -32,6 +32,7 @@
 #include <igl/gaussian_curvature.h>
 #include <igl/grad.h>
 #include <igl/harmonic.h>
+#include <igl/hsv_to_rgb.h>
 #include <igl/internal_angles.h>
 #include <igl/invert_diag.h>
 #include <igl/is_irregular_vertex.h>
@@ -52,6 +53,7 @@
 #include <igl/polar_svd.h>
 #include <igl/principal_curvature.h>
 #include <igl/quad_planarity.h>
+#include <igl/randperm.h>
 #include <igl/readDMAT.h>
 #include <igl/readMESH.h>
 #include <igl/readOBJ.h>
@@ -105,6 +107,7 @@ void python_export_igl(py::module &m)
 #include "py_igl/py_gaussian_curvature.cpp"
 #include "py_igl/py_grad.cpp"
 #include "py_igl/py_harmonic.cpp"
+#include "py_igl/py_hsv_to_rgb.cpp"
 #include "py_igl/py_internal_angles.cpp"
 #include "py_igl/py_invert_diag.cpp"
 #include "py_igl/py_is_irregular_vertex.cpp"
@@ -125,6 +128,7 @@ void python_export_igl(py::module &m)
 #include "py_igl/py_polar_svd.cpp"
 #include "py_igl/py_principal_curvature.cpp"
 #include "py_igl/py_quad_planarity.cpp"
+#include "py_igl/py_randperm.cpp"
 #include "py_igl/py_readDMAT.cpp"
 #include "py_igl/py_readMESH.cpp"
 #include "py_igl/py_readOBJ.cpp"

+ 37 - 0
python/py_igl/embree/py_reorient_facets_raycast.cpp

@@ -0,0 +1,37 @@
+
+
+m.def("reorient_facets_raycast", []
+(
+  const Eigen::MatrixXd& V,
+  const Eigen::MatrixXi& F,
+  int rays_total,
+  int rays_minimum,
+  bool facet_wise,
+  bool use_parity,
+  bool is_verbose,
+  Eigen::MatrixXi& I,
+  Eigen::MatrixXi& C
+)
+{
+  Eigen::VectorXi Iv;
+  Eigen::VectorXi Cv;
+  igl::embree::reorient_facets_raycast(V, F, rays_total, rays_minimum, facet_wise, use_parity, is_verbose, Iv, Cv);
+  I = Iv;
+  C = Cv;
+}, __doc_igl_embree_reorient_facets_raycast,
+py::arg("V"), py::arg("F"), py::arg("rays_total"), py::arg("rays_minimum"), py::arg("facet_wise"), py::arg("use_parity"), py::arg("is_verbose"), py::arg("I"), py::arg("C"));
+
+m.def("reorient_facets_raycast", []
+(
+  const Eigen::MatrixXd& V,
+  const Eigen::MatrixXi& F,
+  Eigen::MatrixXi& FF,
+  Eigen::MatrixXi& I
+)
+{
+  Eigen::VectorXi Iv;
+  igl::embree::reorient_facets_raycast(V, F, FF, Iv);
+  I = Iv;
+}, __doc_igl_embree_reorient_facets_raycast,
+py::arg("V"), py::arg("F"), py::arg("FF"), py::arg("I"));
+

+ 44 - 0
python/py_igl/py_hsv_to_rgb.cpp

@@ -0,0 +1,44 @@
+// COMPLETE BINDINGS ========================
+
+
+m.def("hsv_to_rgb", []
+(
+  const Eigen::MatrixXd& H,
+  Eigen::MatrixXd& R
+)
+{
+  return igl::hsv_to_rgb(H, R);
+}, __doc_igl_hsv_to_rgb,
+py::arg("H"), py::arg("R"));
+
+
+
+
+
+// INCOMPLETE BINDINGS ========================
+
+
+//m.def("hsv_to_rgb", []
+//(
+//  T * hsv,
+//  T * rgb
+//)
+//{
+//  return igl::hsv_to_rgb(hsv, rgb);
+//}, __doc_igl_hsv_to_rgb,
+//py::arg("hsv"), py::arg("rgb"));
+
+//m.def("hsv_to_rgb", []
+//(
+//  T & h,
+//  T & s,
+//  T & v,
+//  T & r,
+//  T & g,
+//  T & b
+//)
+//{
+//  return igl::hsv_to_rgb(h, s, v, r, g, b);
+//}, __doc_igl_hsv_to_rgb,
+//py::arg("h"), py::arg("s"), py::arg("v"), py::arg("r"), py::arg("g"), py::arg("b"));
+

+ 10 - 0
python/py_igl/py_randperm.cpp

@@ -0,0 +1,10 @@
+m.def("randperm", []
+(
+  int n,
+  Eigen::MatrixXi& I
+)
+{
+  return igl::randperm(n, I);
+}, __doc_igl_randperm,
+py::arg("n"), py::arg("I"));
+

+ 3 - 8
python/python_shared.cpp

@@ -30,10 +30,6 @@ extern void python_export_igl_triangle(py::module &);
 extern void python_export_igl_cgal(py::module &);
 #endif
 
-#ifdef PY_COPYLEFT
-extern void python_export_igl_copyleft(py::module &);
-#endif
-
 #ifdef PY_PNG
 extern void python_export_igl_png(py::module &);
 #endif
@@ -78,12 +74,14 @@ PYBIND11_PLUGIN(pyigl) {
            edge_lengths
            eigs
            embree_ambient_occlusion
+           embree_reorient_facets_raycast
            find_cross_field_singularities
            fit_rotations
            floor
            gaussian_curvature
            grad
            harmonic
+           hsv_to_rgb
            internal_angles
            invert_diag
            is_irregular_vertex
@@ -106,6 +104,7 @@ PYBIND11_PLUGIN(pyigl) {
            polar_svd
            principal_curvature
            quad_planarity
+           randperm
            readDMAT
            readMESH
            readOBJ
@@ -157,10 +156,6 @@ PYBIND11_PLUGIN(pyigl) {
     python_export_igl_cgal(m);
     #endif
 
-    #ifdef PY_COPYLEFT
-    python_export_igl_copyleft(m);
-    #endif
-
     #ifdef PY_PNG
     python_export_igl_png(m);
     #endif

+ 1 - 1
python/tutorial/702_WindingNumber.py

@@ -6,7 +6,7 @@ import pyigl as igl
 
 from shared import TUTORIAL_SHARED_PATH, check_dependencies, print_usage
 
-dependencies = []
+dependencies = ["viewer"]
 check_dependencies(dependencies)
 
 

+ 1 - 1
python/tutorial/705_MarchingCubes.py

@@ -6,7 +6,7 @@ import pyigl as igl
 
 from shared import TUTORIAL_SHARED_PATH, check_dependencies, print_usage
 
-dependencies = ["copyleft"]
+dependencies = ["copyleft", "viewer"]
 check_dependencies(dependencies)
 
 

+ 78 - 0
python/tutorial/706_FacetOrientation.py

@@ -0,0 +1,78 @@
+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, print_usage
+
+dependencies = ["embree", "viewer"]
+check_dependencies(dependencies)
+
+
+def key_down(viewer, key, modifier):
+    global facetwise, is_showing_reoriented, FF
+    if key == ord('F') or key == ord('f'):
+        facetwise = (facetwise + 1) % 2
+    elif key == ord('S') or key == ord('s'):
+        scramble_colors()
+    elif key == ord(' '):
+        is_showing_reoriented = ~is_showing_reoriented
+
+    viewer.data.clear()
+    viewer.data.set_mesh(V, FF[facetwise] if is_showing_reoriented else F)
+    viewer.data.set_colors(RGBcolors[facetwise])
+
+    return True
+
+def scramble_colors():
+    global C, viewer, RGBcolors
+    for p in range(2):
+        R = igl.eigen.MatrixXi()
+        igl.randperm(C[p].maxCoeff() + 1, R)
+        C[p] = igl.slice(R, igl.eigen.MatrixXi(C[p]))
+        HSV = igl.eigen.MatrixXd(C[p].rows(), 3)
+        HSV.setCol(0, 360.0 * C[p].castdouble() / C[p].maxCoeff())
+        HSVright = igl.eigen.MatrixXd(HSV.rows(), 2)
+        HSVright.setConstant(1.0)
+        HSV.setRightCols(2, HSVright)
+        igl.hsv_to_rgb(HSV, RGBcolors[p])
+    viewer.data.set_colors(RGBcolors[facetwise])
+
+
+
+if __name__ == "__main__":
+    keys = {"space": "toggle between original and reoriented faces",
+            "F,f": "toggle between patchwise and facetwise reorientation",
+            "S,s": "scramble colors"}
+    print_usage(keys)
+
+    V = igl.eigen.MatrixXd()
+    F = igl.eigen.MatrixXi()
+    C = [igl.eigen.MatrixXi(), igl.eigen.MatrixXi()]
+    RGBcolors = [igl.eigen.MatrixXd(), igl.eigen.MatrixXd()]
+    FF = [igl.eigen.MatrixXi(), igl.eigen.MatrixXi()]
+    is_showing_reoriented = False
+    facetwise = 0
+
+    igl.read_triangle_mesh(TUTORIAL_SHARED_PATH + "truck.obj", V, F)
+
+    # Compute patches
+    for p in range(2):
+        I = igl.eigen.MatrixXi()
+        igl.embree.reorient_facets_raycast(V, F, F.rows() * 100, 10, p == 1, False, False, I, C[p])
+        # apply reorientation
+        FF[p].conservativeResize(F.rows(), F.cols())
+        for i in range(I.rows()):
+            if I[i]:
+                FF[p].setRow(i, F.row(i).rowwiseReverse())
+            else:
+                FF[p].setRow(i, F.row(i))
+
+    # Plot the generated mesh
+    viewer = igl.viewer.Viewer()
+    viewer.data.set_mesh(V, FF[facetwise] if is_showing_reoriented else F)
+    viewer.data.set_face_based(True)
+    scramble_colors()
+    viewer.callback_key_down = key_down
+    viewer.launch()