Browse Source

Merge pull request #292 from s-koch/python_bindings

Python bindings: Added tutorial 701

Former-commit-id: 657e35d2d46af7b5610e82957f6f120487825797
Daniele Panozzo 9 years ago
parent
commit
1d08f33f5e

+ 1 - 0
include/igl/parula.cpp

@@ -69,4 +69,5 @@ template void igl::parula<double>(double, double*);
 template void igl::parula<double>(double, double&, double&, double&);
 template void igl::parula<Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, bool, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
 template void igl::parula<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, bool, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
+template void igl::parula<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, double, double, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
 #endif

+ 1 - 0
python/modules/py_vector.cpp

@@ -153,6 +153,7 @@ py::class_<Type> bind_eigen_2(py::module &m, const char *name,
         .def("trace", [](const Type &m) {return m.trace();})
         .def("norm", [](const Type &m) {return m.norm();})
         .def("squaredNorm", [](const Type &m) {return m.squaredNorm();})
+        .def("squaredMean", [](const Type &m) {return m.array().square().mean();})
 
         .def("minCoeff", [](const Type &m) {return m.minCoeff();} )
         .def("maxCoeff", [](const Type &m) {return m.maxCoeff();} )

+ 19 - 0
python/py_doc.cpp

@@ -421,12 +421,31 @@ 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_internal_angles = R"igl_Qu8mg5v7(// Compute internal angles for a triangle mesh
+  //
+  // Inputs:
+  //   V  #V by dim eigen Matrix of mesh vertex nD positions
+  //   F  #F by poly-size eigen Matrix of face (triangle) indices
+  // Output:
+  //   K  #F by poly-size eigen Matrix of internal angles
+  //     for triangles, columns correspond to edges [1,2],[2,0],[0,1]
+  //
+  // Known Issues:
+  //   if poly-size ≠ 3 then dim must equal 3.)igl_Qu8mg5v7";
 const char *__doc_igl_invert_diag = R"igl_Qu8mg5v7(// Templates:
   //   T  should be a eigen sparse matrix primitive type like int or double
   // Inputs:
   //   X  an m by n sparse matrix
   // Outputs:
   //   Y  an m by n sparse matrix)igl_Qu8mg5v7";
+const char *__doc_igl_is_irregular_vertex = R"igl_Qu8mg5v7(// Determine if a vertex is irregular, i.e. it has more than 6 (triangles)
+  // or 4 (quads) incident edges. Vertices on the boundary are ignored.
+  //
+  // Inputs:
+  //   V  #V by dim list of vertex positions
+  //   F  #F by 3[4] list of triangle[quads] indices
+  // Returns #V vector of bools revealing whether vertices are singular
+  //)igl_Qu8mg5v7";
 const char *__doc_igl_jet = R"igl_Qu8mg5v7(// JET like MATLAB's jet
   //
   // Inputs:

+ 2 - 0
python/py_doc.h

@@ -33,7 +33,9 @@ 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_internal_angles;
 extern const char *__doc_igl_invert_diag;
+extern const char *__doc_igl_is_irregular_vertex;
 extern const char *__doc_igl_jet;
 extern const char *__doc_igl_local_basis;
 extern const char *__doc_igl_lscm;

+ 4 - 0
python/py_igl.cpp

@@ -31,7 +31,9 @@
 #include <igl/gaussian_curvature.h>
 #include <igl/grad.h>
 #include <igl/harmonic.h>
+#include <igl/internal_angles.h>
 #include <igl/invert_diag.h>
+#include <igl/is_irregular_vertex.h>
 #include <igl/jet.h>
 #include <igl/local_basis.h>
 #include <igl/lscm.h>
@@ -100,7 +102,9 @@ 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_internal_angles.cpp"
 #include "py_igl/py_invert_diag.cpp"
+#include "py_igl/py_is_irregular_vertex.cpp"
 #include "py_igl/py_jet.cpp"
 #include "py_igl/py_local_basis.cpp"
 #include "py_igl/py_lscm.cpp"

+ 23 - 0
python/py_igl/py_internal_angles.cpp

@@ -0,0 +1,23 @@
+
+
+m.def("internal_angles", []
+(
+  const Eigen::MatrixXd& V,
+  const Eigen::MatrixXi& F,
+  Eigen::MatrixXd& K
+)
+{
+  return igl::internal_angles(V, F, K);
+}, __doc_igl_internal_angles,
+py::arg("V"), py::arg("F"), py::arg("K"));
+
+m.def("internal_angles", []
+(
+  const Eigen::MatrixXd& L,
+  Eigen::MatrixXd& K
+)
+{
+  return igl::internal_angles(L, K);
+}, __doc_igl_internal_angles,
+py::arg("L"), py::arg("K"));
+

+ 12 - 0
python/py_igl/py_is_irregular_vertex.cpp

@@ -0,0 +1,12 @@
+
+
+m.def("is_irregular_vertex", []
+(
+  const Eigen::MatrixXd& V,
+  const Eigen::MatrixXi& F
+)
+{
+  return igl::is_irregular_vertex(V, F);
+}, __doc_igl_is_irregular_vertex,
+py::arg("V"), py::arg("F"));
+

+ 2 - 0
python/python_shared.cpp

@@ -78,7 +78,9 @@ PYBIND11_PLUGIN(pyigl) {
            gaussian_curvature
            grad
            harmonic
+           internal_angles
            invert_diag
+           is_irregular_vertex
            jet
            local_basis
            lscm

+ 56 - 0
python/tutorial/701_Statistics.py

@@ -0,0 +1,56 @@
+import sys, os
+
+# Add the igl library to the modules search path
+import math
+
+sys.path.insert(0, os.getcwd() + "/../")
+import pyigl as igl
+
+from shared import TUTORIAL_SHARED_PATH, check_dependencies
+
+dependencies = []
+check_dependencies(dependencies)
+
+if __name__ == "__main__":
+    V = igl.eigen.MatrixXd()
+    F = igl.eigen.MatrixXi()
+
+    # Load meshes in OFF format
+    igl.readOBJ(TUTORIAL_SHARED_PATH + "horse_quad.obj", V, F)
+
+    # Count the number of irregular vertices, the border is ignored
+    irregular = igl.is_irregular_vertex(V, F)
+    vertex_count = V.rows()
+    irregular_vertex_count = sum(irregular)
+    irregular_ratio = irregular_vertex_count / vertex_count
+
+    print("Irregular vertices: \n%d/%d (%.2f%%)\n" % (
+        irregular_vertex_count, vertex_count, irregular_ratio * 100))
+
+    # Compute areas, min, max and standard deviation
+    area = igl.eigen.MatrixXd()
+    igl.doublearea(V, F, area)
+    area /= 2.0
+
+    area_avg = area.mean()
+    area_min = area.minCoeff() / area_avg
+    area_max = area.maxCoeff() / area_avg
+    area_ns = (area - area_avg) / area_avg
+    area_sigma = math.sqrt(area_ns.squaredMean())
+
+    print("Areas (Min/Max)/Avg_Area Sigma: \n%.2f/%.2f (%.2f)\n" % (
+        area_min, area_max, area_sigma))
+
+    # Compute per face angles, min, max and standard deviation
+    angles = igl.eigen.MatrixXd()
+    igl.internal_angles(V, F, angles)
+    angles = 360.0 * (angles / (2 * math.pi))
+
+    angle_avg = angles.mean()
+    angle_min = angles.minCoeff()
+    angle_max = angles.maxCoeff()
+    angle_ns = angles - angle_avg
+    angle_sigma = math.sqrt(angle_ns.squaredMean())
+
+    print("Angles in degrees (Min/Max) Sigma: \n%.2f/%.2f (%.2f)\n" % (
+        angle_min, angle_max, angle_sigma))