test_kdtreeindirect.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. #include <catch2/catch.hpp>
  2. #include "libslic3r/KDTreeIndirect.hpp"
  3. #include "libslic3r/Execution/ExecutionSeq.hpp"
  4. #include "libslic3r/BoundingBox.hpp"
  5. #include "libslic3r/PointGrid.hpp"
  6. using namespace Slic3r;
  7. //template<class G>
  8. //struct Within { // Wrapper for the `within` predicate that counts calls.
  9. // kdtree::Within<G> pred;
  10. // Within(G box): pred{box} {}
  11. // // Number of times the predicate was called
  12. // mutable size_t call_count = 0;
  13. // std::pair<bool, unsigned int> operator() (const Vec3f &p, size_t dim)
  14. // {
  15. // ++call_count;
  16. // return pred(p, dim);
  17. // }
  18. //};
  19. static double volume(const BoundingBox3Base<Vec3f> &box)
  20. {
  21. auto sz = box.size();
  22. return sz.x() * sz.y() * sz.z();
  23. }
  24. TEST_CASE("Test kdtree query for a Box", "[KDTreeIndirect]")
  25. {
  26. auto vol = BoundingBox3Base<Vec3f>{{0.f, 0.f, 0.f}, {10.f, 10.f, 10.f}};
  27. auto pgrid = point_grid(ex_seq, vol, Vec3f{0.1f, 0.1f, 0.1f});
  28. REQUIRE(!pgrid.empty());
  29. auto coordfn = [&pgrid] (size_t i, size_t D) { return pgrid.get(i)(int(D)); };
  30. KDTreeIndirect<3, float, decltype(coordfn)> tree{coordfn, pgrid.point_count()};
  31. std::vector<size_t> out;
  32. auto qbox = BoundingBox3Base{Vec3f{0.f, 0.f, 0.f}, Vec3f{.5f, .5f, .5f}};
  33. size_t call_count = 0;
  34. out = find_nearby_points(tree, qbox.min, qbox.max, [&call_count](size_t) {
  35. call_count++;
  36. return true;
  37. });
  38. // Output shall be non-empty
  39. REQUIRE(!out.empty());
  40. std::sort(out.begin(), out.end());
  41. // No duplicates allowed in the output
  42. auto it = std::unique(out.begin(), out.end());
  43. REQUIRE(it == out.end());
  44. // Test if inside points are in the output and outside points are not.
  45. bool succ = true;
  46. for (size_t i = 0; i < pgrid.point_count(); ++i) {
  47. auto foundit = std::find(out.begin(), out.end(), i);
  48. bool contains = qbox.contains(pgrid.get(i));
  49. succ = succ && contains ? foundit != out.end() : foundit == out.end();
  50. if (!succ) {
  51. std::cout << "invalid point: " << i << " " << pgrid.get(i).transpose()
  52. << std::endl;
  53. break;
  54. }
  55. }
  56. REQUIRE(succ);
  57. // Test for the expected cost of the query.
  58. double gridvolume = volume(vol);
  59. double queryvolume = volume(qbox);
  60. double volratio = (queryvolume / gridvolume);
  61. REQUIRE(call_count < 3 * volratio * pgrid.point_count());
  62. REQUIRE(call_count < pgrid.point_count());
  63. }
  64. //TEST_CASE("Test kdtree query for a Sphere", "[KDTreeIndirect]") {
  65. // auto vol = BoundingBox3Base<Vec3f>{{0.f, 0.f, 0.f}, {10.f, 10.f, 10.f}};
  66. // auto pgrid = point_grid(ex_seq, vol, Vec3f{0.1f, 0.1f, 0.1f});
  67. // REQUIRE(!pgrid.empty());
  68. // auto coordfn = [&pgrid] (size_t i, size_t D) { return pgrid.get(i)(int(D)); };
  69. // kdtree::KDTreeIndirect<3, float, decltype(coordfn)> tree{coordfn, pgrid.point_count()};
  70. // std::vector<size_t> out;
  71. // auto querysphere = kdtree::Sphere{Vec3f{5.f, 5.f, 5.f}, 2.f};
  72. // auto pred = Within(querysphere);
  73. // kdtree::query(tree, pred, std::back_inserter(out));
  74. // // Output shall be non-empty
  75. // REQUIRE(!out.empty());
  76. // std::sort(out.begin(), out.end());
  77. // // No duplicates allowed in the output
  78. // auto it = std::unique(out.begin(), out.end());
  79. // REQUIRE(it == out.end());
  80. // // Test if inside points are in the output and outside points are not.
  81. // bool succ = true;
  82. // for (size_t i = 0; i < pgrid.point_count(); ++i) {
  83. // auto foundit = std::find(out.begin(), out.end(), i);
  84. // bool contains = (querysphere.center - pgrid.get(i)).squaredNorm() < pred.pred.r2;
  85. // succ = succ && contains ? foundit != out.end() : foundit == out.end();
  86. // if (!succ) {
  87. // std::cout << "invalid point: " << i << " " << pgrid.get(i).transpose()
  88. // << std::endl;
  89. // break;
  90. // }
  91. // }
  92. // REQUIRE(succ);
  93. // // Test for the expected cost of the query.
  94. // double gridvolume = volume(vol);
  95. // double queryvolume = volume(querysphere);
  96. // double volratio = (queryvolume / gridvolume);
  97. // REQUIRE(pred.call_count < 3 * volratio * pgrid.point_count());
  98. // REQUIRE(pred.call_count < pgrid.point_count());
  99. //}