#include #include #include #include #include #include #include #include #include #include #include #include Eigen::MatrixXd V,U; Eigen::MatrixXi F; Eigen::SparseMatrix L; igl::opengl::glfw::Viewer viewer; int main(int argc, char *argv[]) { using namespace Eigen; using namespace std; // Load a mesh in OFF format igl::readOFF(TUTORIAL_SHARED_PATH "/cow.off", V, F); // Compute Laplace-Beltrami operator: #V by #V igl::cotmatrix(V,F,L); // Alternative construction of same Laplacian SparseMatrix G,K; // Gradient/Divergence igl::grad(V,F,G); // Diagonal per-triangle "mass matrix" VectorXd dblA; igl::doublearea(V,F,dblA); // Place areas along diagonal #dim times const auto & T = 1.*(dblA.replicate(3,1)*0.5).asDiagonal(); // Laplacian K built as discrete divergence of gradient or equivalently // discrete Dirichelet energy Hessian K = -G.transpose() * T * G; cout<<"|K-L|: "<<(K-L).norm()<bool { switch(key) { case 'r': case 'R': U = V; break; case ' ': { // Recompute just mass matrix on each step SparseMatrix M; igl::massmatrix(U,F,igl::MASSMATRIX_TYPE_BARYCENTRIC,M); // Solve (M-delta*L) U = M*U const auto & S = (M - 0.001*L); Eigen::SimplicialLLT > solver(S); assert(solver.info() == Eigen::Success); U = solver.solve(M*U).eval(); // Compute centroid and subtract (also important for numerics) VectorXd dblA; igl::doublearea(U,F,dblA); double area = 0.5*dblA.sum(); MatrixXd BC; igl::barycenter(U,F,BC); RowVector3d centroid(0,0,0); for(int i = 0;i