fast_winding_number.cpp 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2019 Alec Jacobson <[email protected]>
  4. //
  5. // This Source Code Form is subject to the terms of the Mozilla Public License
  6. // v. 2.0. If a copy of the MPL was not distributed with this file, You can
  7. // obtain one at http://mozilla.org/MPL/2.0/.
  8. #include <test_common.h>
  9. #include <igl/read_triangle_mesh.h>
  10. #include <igl/winding_number.h>
  11. #include <igl/fast_winding_number.h>
  12. #include <igl/octree.h>
  13. #include <igl/barycenter.h>
  14. #include <igl/per_face_normals.h>
  15. #include <igl/doublearea.h>
  16. TEST_CASE("fast_winding_number: one_point_cloud", "[igl]")
  17. {
  18. Eigen::MatrixXd P(1,3);
  19. P<<0.1,0.2,0.3;
  20. // Unit normal
  21. Eigen::MatrixXd N(1,3);
  22. N<<4,5,6;
  23. N /= N.row(0).norm();
  24. Eigen::VectorXd A(1,1);
  25. A(0) = 0.7;
  26. std::vector<std::vector<int > > O_PI;
  27. Eigen::MatrixXi O_CH;
  28. Eigen::MatrixXd O_CN;
  29. Eigen::VectorXd O_W;
  30. igl::octree(P,O_PI,O_CH,O_CN,O_W);
  31. Eigen::MatrixXd O_CM;
  32. Eigen::VectorXd O_R;
  33. Eigen::MatrixXd O_EC;
  34. igl::fast_winding_number(P,N,A,O_PI,O_CH,2,O_CM,O_R,O_EC);
  35. Eigen::MatrixXd Q(4,3);
  36. Q<<
  37. 0, 0, 0,
  38. 4,-3, 2,
  39. -1, 1, 3,
  40. 0, 5,-2;
  41. Eigen::VectorXd WiP;
  42. igl::fast_winding_number(P,N,A,O_PI,O_CH,O_CM,O_R,O_EC,Q,2,WiP);
  43. Eigen::VectorXd WiP_cached(4);
  44. WiP_cached<<
  45. 0.38779369004261133,
  46. -0.00041235296362485,
  47. -0.00362978253577090,
  48. -0.00041235296362485;
  49. test_common::assert_near(WiP,WiP_cached,1e-15);
  50. }
  51. TEST_CASE("fast_winding_number: meshes", "[igl]" "[slow]")
  52. {
  53. const auto test_case = [](const std::string &param)
  54. {
  55. INFO(param);
  56. Eigen::MatrixXd V;
  57. Eigen::MatrixXi F;
  58. igl::read_triangle_mesh(test_common::data_path(param),V,F);
  59. // vertex centroid will be our query
  60. Eigen::MatrixXd Q = V.array().colwise().mean();
  61. Eigen::VectorXd Wexact(1,1);
  62. Wexact(0,0) = igl::winding_number(V,F,Eigen::RowVector3d(Q));
  63. // SOUP
  64. {
  65. INFO("soup");
  66. igl::FastWindingNumberBVH fwn_bvh;
  67. igl::fast_winding_number(V,F,2,fwn_bvh);
  68. Eigen::VectorXd Wfwn_soup;
  69. igl::fast_winding_number(fwn_bvh,2,Q,Wfwn_soup);
  70. test_common::assert_near(Wfwn_soup,Wexact,1e-2);
  71. }
  72. // CLOUD
  73. // triangle barycenters, normals and areas will be our point cloud
  74. {
  75. INFO("cloud");
  76. Eigen::MatrixXd BC,N;
  77. Eigen::VectorXd A;
  78. igl::barycenter(V,F,BC);
  79. igl::per_face_normals(V,F,N);
  80. igl::doublearea(V,F,A);
  81. A *= 0.5;
  82. Eigen::VectorXd Wfwn_cloud;
  83. std::vector<std::vector<int > > O_PI;
  84. Eigen::MatrixXi O_CH;
  85. Eigen::MatrixXd O_CN;
  86. Eigen::VectorXd O_W;
  87. igl::octree(BC,O_PI,O_CH,O_CN,O_W);
  88. Eigen::MatrixXd O_CM;
  89. Eigen::VectorXd O_R;
  90. Eigen::MatrixXd O_EC;
  91. igl::fast_winding_number(BC,N,A,O_PI,O_CH,2,O_CM,O_R,O_EC);
  92. igl::fast_winding_number(BC,N,A,O_PI,O_CH,O_CM,O_R,O_EC,Q,2,Wfwn_cloud);
  93. test_common::assert_near(Wfwn_cloud,Wexact,1e-2);
  94. }
  95. };
  96. // FWN clouds using barycenters won't work well for very coarse models like the cube
  97. test_common::run_test_cases<std::string>(
  98. {"bunny.off", "elephant.off", "hemisphere.obj"},
  99. test_case);
  100. }