main.cpp 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. #include <igl/read_triangle_mesh.h>
  2. #include <igl/hessian_energy.h>
  3. #include <igl/massmatrix.h>
  4. #include <igl/cotmatrix.h>
  5. #include <igl/isolines_map.h>
  6. #include <igl/parula.h>
  7. #include <igl/vertex_components.h>
  8. #include <igl/remove_unreferenced.h>
  9. #include <igl/opengl/glfw/Viewer.h>
  10. #include <Eigen/Core>
  11. #include <Eigen/SparseCholesky>
  12. #include <iostream>
  13. #include <set>
  14. #include <limits>
  15. #include <stdlib.h>
  16. #include "tutorial_shared_path.h"
  17. int main(int argc, char * argv[])
  18. {
  19. typedef Eigen::SparseMatrix<double> SparseMat;
  20. //Read our mesh
  21. Eigen::MatrixXd V;
  22. Eigen::MatrixXi F;
  23. if(!igl::read_triangle_mesh(
  24. argc>1?argv[1]: TUTORIAL_SHARED_PATH "/beetle.off",V,F)) {
  25. std::cout << "Failed to load mesh." << std::endl;
  26. }
  27. //Constructing an exact function to smooth
  28. Eigen::VectorXd zexact = V.block(0,2,V.rows(),1).array()
  29. + 0.5*V.block(0,1,V.rows(),1).array()
  30. + V.block(0,1,V.rows(),1).array().pow(2)
  31. + V.block(0,2,V.rows(),1).array().pow(3);
  32. //Make the exact function noisy
  33. srand(5);
  34. const double s = 0.2*(zexact.maxCoeff() - zexact.minCoeff());
  35. Eigen::VectorXd znoisy = zexact + s*Eigen::VectorXd::Random(zexact.size());
  36. //Constructing the squared Laplacian and squared Hessian energy
  37. SparseMat L, M;
  38. igl::cotmatrix(V, F, L);
  39. igl::massmatrix(V, F, igl::MASSMATRIX_TYPE_BARYCENTRIC, M);
  40. Eigen::SimplicialLDLT<SparseMat> solver(M);
  41. SparseMat MinvL = solver.solve(L);
  42. SparseMat QL = L.transpose()*MinvL;
  43. SparseMat QH;
  44. igl::hessian_energy(V, F, QH);
  45. //Solve to find Laplacian-smoothed and Hessian-smoothed solutions
  46. const double al = 8e-4;
  47. Eigen::SimplicialLDLT<SparseMat> lapSolver(al*QL + (1.-al)*M);
  48. Eigen::VectorXd zl = lapSolver.solve(al*M*znoisy);
  49. const double ah = 5e-6;
  50. Eigen::SimplicialLDLT<SparseMat> hessSolver(ah*QH + (1.-ah)*M);
  51. Eigen::VectorXd zh = hessSolver.solve(ah*M*znoisy);
  52. //Viewer that shows all functions: zexact, znoisy, zl, zh
  53. igl::opengl::glfw::Viewer viewer;
  54. viewer.data().set_mesh(V,F);
  55. viewer.data().show_lines = false;
  56. viewer.callback_key_down =
  57. [&](igl::opengl::glfw::Viewer & viewer, unsigned char key, int mod)->bool
  58. {
  59. //Graduate result to show isolines, then compute color matrix
  60. const Eigen::VectorXd* z;
  61. switch(key) {
  62. case '1':
  63. z = &zexact;
  64. break;
  65. case '2':
  66. z = &znoisy;
  67. break;
  68. case '3':
  69. z = &zl;
  70. break;
  71. case '4':
  72. z = &zh;
  73. break;
  74. default:
  75. return false;
  76. }
  77. viewer.data().set_data(*z);
  78. return true;
  79. };
  80. std::cout << R"(Usage:
  81. 1 Show original function
  82. 2 Show noisy function
  83. 3 Biharmonic smoothing (zero Neumann boundary)
  84. 4 Biharmonic smoothing (natural Hessian boundary)
  85. )";
  86. Eigen::MatrixXd CM;
  87. igl::parula(Eigen::VectorXd::LinSpaced(21,0,1).eval(),false,CM);
  88. igl::isolines_map(Eigen::MatrixXd(CM),CM);
  89. viewer.data().set_colormap(CM);
  90. viewer.data().set_data(znoisy);
  91. viewer.launch();
  92. return 0;
  93. }