diff --git a/.gitignore b/.gitignore index d0d268072..145cdf08f 100644 --- a/.gitignore +++ b/.gitignore @@ -82,3 +82,4 @@ Untitled.ipynb python/.ipynb_checkpoints py_doc.cpp py_doc.h +python/py_igl/todo diff --git a/python/201_Normals.py b/python/201_Normals.py index ce673bdad..cd6a6e3a2 100755 --- a/python/201_Normals.py +++ b/python/201_Normals.py @@ -1,24 +1,21 @@ - - +import igl # Load a mesh in OFF format V = igl.eigen.MatrixXd() F = igl.eigen.MatrixXi() -igl.readOFF("../shared/fandisk.off", V, F); +igl.readOFF("../tutorial/shared/fandisk.off", V, F); # Compute per-face normals N_faces = igl.eigen.MatrixXd() -igl::per_face_normals(V,F,N_faces); +igl.per_face_normals(V,F,N_faces); print("igl::per_face_normals: \n", N_faces, sep='') # Compute per-vertex normals N_vertices = igl.eigen.MatrixXd() -igl::per_vertex_normals(V,F,N_vertices); -print("igl::per_face_normals: \n", N_vertices, sep='') +igl.per_vertex_normals(V,F,igl.PER_VERTEX_NORMALS_WEIGHTING_TYPE_AREA,N_vertices); +print("igl::per_vertex_normals: \n", N_vertices, sep='') # Compute per-corner normals, |dihedral angle| > 20 degrees --> crease N_corners = igl.eigen.MatrixXd() -igl::per_corner_normals(V,F,20,N_corners); -print("igl::per_face_normals: \n", N_corners, sep='') - -} +igl.per_corner_normals(V,F,20,N_corners); +print("igl::per_corner_normals: \n", N_corners, sep='') diff --git a/python/202_GaussianCurvature.py b/python/202_GaussianCurvature.py new file mode 100644 index 000000000..3946ccff8 --- /dev/null +++ b/python/202_GaussianCurvature.py @@ -0,0 +1,17 @@ +import igl + +# Load mesh +V = igl.eigen.MatrixXd(); +F = igl.eigen.MatrixXi(); +igl.readOFF("../tutorial/shared/bumpy.off",V,F); + +# Compute Gaussian curvature +K = igl.eigen.VectorXd(); +igl.gaussian_curvature(V,F,K); + +print("igl::gaussian_curvature: \n", K, sep='') + +# Compute pseudocolor +C = igl.eigen.MatrixXd(); +igl.jet(K,True,C); +print("igl::jet: \n", C, sep='') diff --git a/python/203_CurvatureDirections.py b/python/203_CurvatureDirections.py new file mode 100755 index 000000000..131ffec7c --- /dev/null +++ b/python/203_CurvatureDirections.py @@ -0,0 +1,56 @@ +import igl + + + + + + std::string filename = "../shared/fertility.off"; + if(argc>1) + { + filename = argv[1]; + } + // Load a mesh in OFF format + igl::read_triangle_mesh(filename, V, F); + + // Alternative discrete mean curvature + MatrixXd HN; + SparseMatrix L,M,Minv; + igl::cotmatrix(V,F,L); + igl::massmatrix(V,F,igl::MASSMATRIX_TYPE_VORONOI,M); + igl::invert_diag(M,Minv); + // Laplace-Beltrami of position + HN = -Minv*(L*V); + // Extract magnitude as mean curvature + VectorXd H = HN.rowwise().norm(); + + // Compute curvature directions via quadric fitting + MatrixXd PD1,PD2; + VectorXd PV1,PV2; + igl::principal_curvature(V,F,PD1,PD2,PV1,PV2); + // mean curvature + H = 0.5*(PV1+PV2); + + igl::viewer::Viewer viewer; + viewer.data.set_mesh(V, F); + + + // Compute pseudocolor + MatrixXd C; + igl::parula(H,true,C); + viewer.data.set_colors(C); + + // Average edge length for sizing + const double avg = igl::avg_edge_length(V,F); + + // Draw a blue segment parallel to the minimal curvature direction + const RowVector3d red(0.8,0.2,0.2),blue(0.2,0.2,0.8); + viewer.data.add_edges(V + PD1*avg, V - PD1*avg, blue); + + // Draw a red segment parallel to the maximal curvature direction + viewer.data.add_edges(V + PD2*avg, V - PD2*avg, red); + + // Hide wireframe + viewer.core.show_lines = false; + + viewer.launch(); +} diff --git a/python/py_igl.cpp b/python/py_igl.cpp index 7d8bc6c90..cf00180bb 100644 --- a/python/py_igl.cpp +++ b/python/py_igl.cpp @@ -1,98 +1,22 @@ #include #include "python.h" + #include #include #include +#include +#include +#include +#include -void python_export_igl(py::module &m) { - -// readOFF.h - - m.def("readOFF", [] - ( - const std::string str, - Eigen::MatrixXd& V, - Eigen::MatrixXi& F - ) - { - return igl::readOFF(str,V,F); - }, __doc_igl_readOFF, - py::arg("str"), py::arg("V"), py::arg("F")); - - m.def("readOFF", [] - ( - const std::string str, - Eigen::MatrixXd& V, - Eigen::MatrixXi& F, - Eigen::MatrixXd& N - ) - { - return igl::readOFF(str,V,F,N); - }, __doc_igl_readOFF, - py::arg("str"), py::arg("V"), py::arg("F"), py::arg("N")); - -// writeOBJ.h -m.def("writeOBJ", [] -( - const std::string str, - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - const Eigen::MatrixXd& CN, - const Eigen::MatrixXi& FN, - const Eigen::MatrixXd& TC, - const Eigen::MatrixXi& FTC -) +void python_export_igl(py::module &m) { - return igl::writeOBJ(str,V,F,CN,FN,TC,FTC); -}, __doc_igl_writeOBJ, -py::arg("str"), py::arg("V"), py::arg("F"), py::arg("CN"), py::arg("FN"), py::arg("TC"), py::arg("FTC")); - -m.def("writeOBJ", [] -( - const std::string str, - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F -) -{ - return igl::writeOBJ(str,V,F); -}, __doc_igl_writeOBJ, -py::arg("str"), py::arg("V"), py::arg("F")); - -// per_face_normals - -m.def("per_face_normals", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - const Eigen::VectorXd& Z, - Eigen::MatrixXd& N -) -{ - return igl::per_face_normals(V,F,Z,N); -}, __doc_igl_per_face_normals, -py::arg("V"), py::arg("F"), py::arg("Z"), py::arg("N")); - -m.def("per_face_normals", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - Eigen::MatrixXd& N -) -{ - return igl::per_face_normals(V,F,N); -}, __doc_igl_per_face_normals, -py::arg("V"), py::arg("F"), py::arg("N")); - -m.def("per_face_normals_stable", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - Eigen::MatrixXd& N -) -{ - return igl::per_face_normals_stable(V,F,N); -}, __doc_igl_per_face_normals, -py::arg("V"), py::arg("F"), py::arg("N")); - +#include "py_igl/py_readOFF.cpp" +#include "py_igl/py_writeOBJ.cpp" +#include "py_igl/py_per_face_normals.cpp" +#include "py_igl/py_per_corner_normals.cpp" +#include "py_igl/py_per_vertex_normals.cpp" +#include "py_igl/py_gaussian_curvature.cpp" +#include "py_igl/py_jet.cpp" } diff --git a/python/py_igl/py_gaussian_curvature.cpp b/python/py_igl/py_gaussian_curvature.cpp new file mode 100644 index 000000000..e2bf30c55 --- /dev/null +++ b/python/py_igl/py_gaussian_curvature.cpp @@ -0,0 +1,10 @@ +m.def("gaussian_curvature", [] +( + const Eigen::MatrixXd& V, + const Eigen::MatrixXi& F, + Eigen::VectorXd& K +) +{ + return igl::gaussian_curvature(V,F,K); +}, __doc_igl_gaussian_curvature, +py::arg("V"), py::arg("F"), py::arg("K")); diff --git a/python/py_igl/py_jet.cpp b/python/py_igl/py_jet.cpp new file mode 100644 index 000000000..e532fa353 --- /dev/null +++ b/python/py_igl/py_jet.cpp @@ -0,0 +1,22 @@ +m.def("jet", [] +( + const Eigen::VectorXd& Z, + const bool normalize, + Eigen::MatrixXd& C +) +{ + return igl::jet(Z,normalize,C); +}, __doc_igl_jet, +py::arg("Z"), py::arg("normalize"), py::arg("C")); + +m.def("jet", [] +( + const Eigen::VectorXd& Z, + const double min_Z, + const double max_Z, + Eigen::MatrixXd& C +) +{ + return igl::jet(Z,min_Z,max_Z,C); +}, __doc_igl_jet, +py::arg("Z"), py::arg("min_Z"), py::arg("max_Z"), py::arg("C")); diff --git a/python/py_igl/py_per_corner_normals.cpp b/python/py_igl/py_per_corner_normals.cpp new file mode 100644 index 000000000..0bddf815e --- /dev/null +++ b/python/py_igl/py_per_corner_normals.cpp @@ -0,0 +1,38 @@ +m.def("per_corner_normals", [] +( + const Eigen::MatrixXd& V, + const Eigen::MatrixXi& F, + const double corner_threshold, + Eigen::MatrixXd& CN +) +{ + return igl::per_corner_normals(V,F,corner_threshold,CN); +}, __doc_igl_per_corner_normals, +py::arg("V"), py::arg("F"), py::arg("corner_threshold"), py::arg("CN")); + +m.def("per_corner_normals", [] +( + const Eigen::MatrixXd& V, + const Eigen::MatrixXi& F, + const Eigen::MatrixXd& FN, + const double corner_threshold, + Eigen::MatrixXd& CN +) +{ + return igl::per_corner_normals(V,F,FN,corner_threshold,CN); +}, __doc_igl_per_corner_normals, +py::arg("V"), py::arg("F"), py::arg("FN"), py::arg("corner_threshold"), py::arg("CN")); + +m.def("per_corner_normals", [] +( + const Eigen::MatrixXd& V, + const Eigen::MatrixXi& F, + const Eigen::MatrixXd& FN, + const double corner_threshold, + const std::vector >& VF, + Eigen::MatrixXd& CN +) +{ + return igl::per_corner_normals(V,F,FN,VF,corner_threshold,CN); +}, __doc_igl_per_corner_normals, +py::arg("V"), py::arg("F"), py::arg("FN"), py::arg("corner_threshold"), py::arg("VF"), py::arg("CN")); diff --git a/python/py_igl/py_per_face_normals.cpp b/python/py_igl/py_per_face_normals.cpp new file mode 100644 index 000000000..622cd7546 --- /dev/null +++ b/python/py_igl/py_per_face_normals.cpp @@ -0,0 +1,33 @@ +m.def("per_face_normals", [] +( + const Eigen::MatrixXd& V, + const Eigen::MatrixXi& F, + const Eigen::VectorXd& Z, + Eigen::MatrixXd& N +) +{ + return igl::per_face_normals(V,F,Z,N); +}, __doc_igl_per_face_normals, +py::arg("V"), py::arg("F"), py::arg("Z"), py::arg("N")); + +m.def("per_face_normals", [] +( + const Eigen::MatrixXd& V, + const Eigen::MatrixXi& F, + Eigen::MatrixXd& N +) +{ + return igl::per_face_normals(V,F,N); +}, __doc_igl_per_face_normals, +py::arg("V"), py::arg("F"), py::arg("N")); + +m.def("per_face_normals_stable", [] +( + const Eigen::MatrixXd& V, + const Eigen::MatrixXi& F, + Eigen::MatrixXd& N +) +{ + return igl::per_face_normals_stable(V,F,N); +}, __doc_igl_per_face_normals, +py::arg("V"), py::arg("F"), py::arg("N")); diff --git a/python/py_igl/py_per_vertex_normals.cpp b/python/py_igl/py_per_vertex_normals.cpp new file mode 100644 index 000000000..3e718d7f6 --- /dev/null +++ b/python/py_igl/py_per_vertex_normals.cpp @@ -0,0 +1,55 @@ +py::enum_(m, "PerVertexNormalsWeightingType") + .value("PER_VERTEX_NORMALS_WEIGHTING_TYPE_UNIFORM", igl::PER_VERTEX_NORMALS_WEIGHTING_TYPE_UNIFORM) + .value("PER_VERTEX_NORMALS_WEIGHTING_TYPE_AREA", igl::PER_VERTEX_NORMALS_WEIGHTING_TYPE_AREA) + .value("PER_VERTEX_NORMALS_WEIGHTING_TYPE_ANGLE", igl::PER_VERTEX_NORMALS_WEIGHTING_TYPE_ANGLE) + .value("PER_VERTEX_NORMALS_WEIGHTING_TYPE_DEFAULT", igl::PER_VERTEX_NORMALS_WEIGHTING_TYPE_DEFAULT) + .value("NUM_PER_VERTEX_NORMALS_WEIGHTING_TYPE", igl::NUM_PER_VERTEX_NORMALS_WEIGHTING_TYPE) + .export_values(); + +m.def("per_vertex_normals", [] +( + const Eigen::MatrixXd& V, + const Eigen::MatrixXi& F, + const igl::PerVertexNormalsWeightingType weighting, + Eigen::MatrixXd& N +) +{ + return igl::per_vertex_normals(V,F,weighting,N); +}, __doc_igl_per_vertex_normals, +py::arg("V"), py::arg("F"), py::arg("weighting"), py::arg("N")); + +m.def("per_vertex_normals", [] +( + const Eigen::MatrixXd& V, + const Eigen::MatrixXi& F, + Eigen::MatrixXd& N +) +{ + return igl::per_vertex_normals(V,F,N); +}, __doc_igl_per_vertex_normals, +py::arg("V"), py::arg("F"), py::arg("N")); + +m.def("per_vertex_normals", [] +( + const Eigen::MatrixXd& V, + const Eigen::MatrixXi& F, + const igl::PerVertexNormalsWeightingType weighting, + const Eigen::MatrixXd& FN, + Eigen::MatrixXd& N +) +{ + return igl::per_vertex_normals(V,F,weighting,FN,N); +}, __doc_igl_per_vertex_normals, +py::arg("V"), py::arg("F"), py::arg("weighting"), py::arg("FN"), py::arg("N")); + +m.def("per_vertex_normals", [] +( + const Eigen::MatrixXd& V, + const Eigen::MatrixXi& F, + const Eigen::MatrixXd& FN, + Eigen::MatrixXd& N +) +{ + return igl::per_vertex_normals(V,F,FN,N); +}, __doc_igl_per_vertex_normals, +py::arg("V"), py::arg("F"), py::arg("FN"), py::arg("N")); diff --git a/python/py_igl/py_readOFF.cpp b/python/py_igl/py_readOFF.cpp new file mode 100644 index 000000000..158d2f41c --- /dev/null +++ b/python/py_igl/py_readOFF.cpp @@ -0,0 +1,22 @@ +m.def("readOFF", [] +( + const std::string str, + Eigen::MatrixXd& V, + Eigen::MatrixXi& F +) +{ + return igl::readOFF(str,V,F); +}, __doc_igl_readOFF, +py::arg("str"), py::arg("V"), py::arg("F")); + +m.def("readOFF", [] +( + const std::string str, + Eigen::MatrixXd& V, + Eigen::MatrixXi& F, + Eigen::MatrixXd& N +) +{ + return igl::readOFF(str,V,F,N); +}, __doc_igl_readOFF, +py::arg("str"), py::arg("V"), py::arg("F"), py::arg("N")); diff --git a/python/py_igl/py_writeOBJ.cpp b/python/py_igl/py_writeOBJ.cpp new file mode 100644 index 000000000..0f1d57ce5 --- /dev/null +++ b/python/py_igl/py_writeOBJ.cpp @@ -0,0 +1,25 @@ +m.def("writeOBJ", [] +( + const std::string str, + const Eigen::MatrixXd& V, + const Eigen::MatrixXi& F, + const Eigen::MatrixXd& CN, + const Eigen::MatrixXi& FN, + const Eigen::MatrixXd& TC, + const Eigen::MatrixXi& FTC +) +{ + return igl::writeOBJ(str,V,F,CN,FN,TC,FTC); +}, __doc_igl_writeOBJ, +py::arg("str"), py::arg("V"), py::arg("F"), py::arg("CN"), py::arg("FN"), py::arg("TC"), py::arg("FTC")); + +m.def("writeOBJ", [] +( + const std::string str, + const Eigen::MatrixXd& V, + const Eigen::MatrixXi& F +) +{ + return igl::writeOBJ(str,V,F); +}, __doc_igl_writeOBJ, +py::arg("str"), py::arg("V"), py::arg("F"));