decimate.cpp 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. #include <test_common.h>
  2. #include <igl/decimate.h>
  3. #include <igl/sort.h>
  4. #include <igl/sortrows.h>
  5. #include <igl/matlab_format.h>
  6. #include <igl/placeholders.h>
  7. #include <iostream>
  8. // class decimate : public ::testing::TestWithParam<std::string> {};
  9. TEST_CASE("decimate: hemisphere", "[igl]")
  10. {
  11. // Load a hemisphere centered at the origin. For each original vertex compute
  12. // its "perfect normal" (i.e., its position treated as unit vectors).
  13. // Decimate the model and using the birth indices of the output vertices grab
  14. // their original "perfect normals" and compare them to their current
  15. // positions treated as unit vectors. If vertices have not moved much, then
  16. // these should be similar (mostly this is checking if the birth indices are
  17. // sane).
  18. Eigen::MatrixXd V,U;
  19. Eigen::MatrixXi F,G;
  20. Eigen::VectorXi J,I;
  21. // Load example mesh: GetParam() will be name of mesh file
  22. igl::read_triangle_mesh(test_common::data_path("hemisphere.obj"), V, F);
  23. // Perfect normals from positions
  24. Eigen::MatrixXd NV = V.rowwise().normalized();
  25. // Remove half of the faces
  26. igl::decimate(V,F,F.rows()/2,false,U,G,J,I);
  27. // Expect that all normals still point in same direction as original
  28. Eigen::MatrixXd NU = U.rowwise().normalized();
  29. Eigen::MatrixXd NVI = NV(I,igl::placeholders::all);
  30. REQUIRE (NU.rows() == NVI.rows());
  31. REQUIRE (NU.cols() == NVI.cols());
  32. // Dot product
  33. Eigen::VectorXd D = (NU.array()*NVI.array()).rowwise().sum();
  34. Eigen::VectorXd O = Eigen::VectorXd::Ones(D.rows());
  35. // 0.2 chosen to succeed on 256 face hemisphere.obj reduced to 128 faces
  36. test_common::assert_near(D,O,0.02);
  37. }
  38. TEST_CASE("decimate: closed", "[igl]")
  39. {
  40. const auto test_case = [](const std::string &param)
  41. {
  42. Eigen::MatrixXd V,U;
  43. Eigen::MatrixXi F,G;
  44. Eigen::VectorXi I,J;
  45. // Load example mesh: GetParam() will be name of mesh file
  46. igl::read_triangle_mesh(test_common::data_path(param), V, F);
  47. igl::decimate(V,F,0,false,U,G,I,J);
  48. REQUIRE (4 == U.rows());
  49. REQUIRE (4 == G.rows());
  50. {
  51. Eigen::MatrixXi _;
  52. igl::sort(Eigen::MatrixXi(G),2,true,G,_);
  53. }
  54. {
  55. Eigen::VectorXi _;
  56. igl::sortrows(Eigen::MatrixXi(G),true,G,_);
  57. }
  58. // Tet with sorted faces
  59. Eigen::MatrixXi T(4,3);
  60. T<<
  61. 0,1,2,
  62. 0,1,3,
  63. 0,2,3,
  64. 1,2,3;
  65. test_common::assert_eq(G,T);
  66. };
  67. test_common::run_test_cases(test_common::closed_genus_0_meshes(), test_case);
  68. }