2
0

main.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. #include <igl/read_triangle_mesh.h>
  2. #include <igl/parula.h>
  3. #include <igl/remove_unreferenced.h>
  4. #include <igl/opengl/glfw/Viewer.h>
  5. #include <igl/per_face_normals.h>
  6. #include <igl/orient_halfedges.h>
  7. #include <igl/cr_vector_laplacian.h>
  8. #include <igl/cr_vector_mass.h>
  9. #include <igl/edge_midpoints.h>
  10. #include <igl/edge_vectors.h>
  11. #include <igl/average_from_edges_onto_vertices.h>
  12. #include <igl/PI.h>
  13. #include <Eigen/Core>
  14. #include <Eigen/SparseCholesky>
  15. #include <Eigen/Geometry>
  16. #include <iostream>
  17. #include <set>
  18. #include <limits>
  19. #include <stdlib.h>
  20. int main(int argc, char * argv[])
  21. {
  22. typedef Eigen::SparseMatrix<double> SparseMat;
  23. //Constants used for smoothing
  24. const double howMuchToSmoothBy = 1e-1;
  25. const int howManySmoothingInterations = 50;
  26. //Read our mesh
  27. Eigen::MatrixXd V;
  28. Eigen::MatrixXi F;
  29. if(!igl::read_triangle_mesh
  30. (argc>1?argv[1]: TUTORIAL_SHARED_PATH "/elephant.obj",V,F)) {
  31. std::cout << "Failed to load mesh." << std::endl;
  32. }
  33. //Orient edges for plotting
  34. Eigen::MatrixXi E, oE;
  35. igl::orient_halfedges(F, E, oE);
  36. //Compute edge midpoints & edge vectors
  37. Eigen::MatrixXd edgeMps, parVec, perpVec;
  38. igl::edge_midpoints(V, F, E, oE, edgeMps);
  39. igl::edge_vectors(V, F, E, oE, parVec, perpVec);
  40. //Constructing a function to add noise to
  41. const auto zraw_function = [] (const Eigen::Vector3d& x) {
  42. return Eigen::Vector3d(0.2*x(1) + cos(2*x(1)+0.2),
  43. 0.5*x(0) + 0.15,
  44. 0.3*cos(0.2+igl::PI*x(2)));
  45. };
  46. Eigen::VectorXd zraw(2*edgeMps.rows());
  47. for(int i=0; i<edgeMps.rows(); ++i) {
  48. const Eigen::Vector3d f = zraw_function(edgeMps.row(i));
  49. zraw(i) = f.dot(parVec.row(i));
  50. zraw(i+edgeMps.rows()) = f.dot(perpVec.row(i));
  51. }
  52. //Add noise
  53. srand(71);
  54. const double l = 15;
  55. Eigen::VectorXd znoisy = zraw + l*Eigen::VectorXd::Random(zraw.size());
  56. //Denoise function using the vector Dirichlet energy
  57. Eigen::VectorXd zsmoothed = znoisy;
  58. for(int i=0; i<howManySmoothingInterations; ++i) {
  59. //Compute Laplacian and mass matrix
  60. SparseMat L, M;
  61. igl::cr_vector_mass(V, F, E, M);
  62. igl::cr_vector_laplacian(V, F, E, oE, L);
  63. //Implicit step
  64. Eigen::SimplicialLDLT<SparseMat> rhsSolver(M + howMuchToSmoothBy*L);
  65. zsmoothed = rhsSolver.solve(M*zsmoothed);
  66. }
  67. //Convert vector fields for plotting
  68. const auto cr_result_to_vecs_and_colors = [&]
  69. (const Eigen::VectorXd& z, Eigen::MatrixXd& vecs, Eigen::MatrixXd& colors) {
  70. vecs.resize(edgeMps.rows(), 3);
  71. for(int i=0; i<edgeMps.rows(); ++i) {
  72. vecs.row(i) = z(i)*parVec.row(i)
  73. + z(i+edgeMps.rows())*perpVec.row(i);
  74. }
  75. igl::average_from_edges_onto_vertices
  76. (F, E, oE, vecs.rowwise().norm().eval(), colors);
  77. };
  78. Eigen::MatrixXd noisyvecs, noisycolors, smoothedvecs, smoothedcolors,
  79. rawvecs, rawcolors;
  80. cr_result_to_vecs_and_colors(znoisy, noisyvecs, noisycolors);
  81. cr_result_to_vecs_and_colors(zsmoothed, smoothedvecs, smoothedcolors);
  82. cr_result_to_vecs_and_colors(zraw, rawvecs, rawcolors);
  83. //Viewer that shows noisy and denoised functions
  84. igl::opengl::glfw::Viewer viewer;
  85. viewer.data().set_mesh(V,F);
  86. viewer.data().show_lines = false;
  87. viewer.callback_key_down =
  88. [&](igl::opengl::glfw::Viewer & viewer, unsigned char key, int mod)->bool
  89. {
  90. const Eigen::MatrixXd *vecs, *colors;
  91. switch(key) {
  92. case '1':
  93. vecs = &rawvecs;
  94. colors = &rawcolors;
  95. break;
  96. case '2':
  97. vecs = &noisyvecs;
  98. colors = &noisycolors;
  99. break;
  100. case '3':
  101. vecs = &smoothedvecs;
  102. colors = &smoothedcolors;
  103. break;
  104. default:
  105. return false;
  106. }
  107. viewer.data().set_data(*colors);
  108. viewer.data().clear_edges();
  109. const double s = 0.08; //How much to scale vectors during plotting
  110. viewer.data().add_edges(edgeMps, edgeMps + s*(*vecs),
  111. Eigen::RowVector3d(0.1, 0.1, 0.1));
  112. return true;
  113. };
  114. std::cout << R"(Usage:
  115. 1 Show raw function
  116. 2 Show noisy function
  117. 3 Show smoothed function
  118. )";
  119. Eigen::MatrixXd CM;
  120. igl::parula(Eigen::VectorXd::LinSpaced
  121. (500,znoisy.minCoeff(), znoisy.maxCoeff()).eval(), true, CM);
  122. viewer.data().set_colormap(CM);
  123. viewer.callback_key_down(viewer, '1', 0);
  124. viewer.launch();
  125. return 0;
  126. }