eytzinger_aabb.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. #include "eytzinger_aabb.h"
  2. #include "PlainMatrix.h"
  3. #include "median.h"
  4. #include <vector>
  5. #include <algorithm>
  6. template <
  7. typename DerivedPB,
  8. typename DerivedB,
  9. typename Derivedleaf
  10. >
  11. IGL_INLINE void igl::eytzinger_aabb(
  12. const Eigen::MatrixBase<DerivedPB> & PB1,
  13. const Eigen::MatrixBase<DerivedPB> & PB2,
  14. Eigen::PlainObjectBase<DerivedB> & B1,
  15. Eigen::PlainObjectBase<DerivedB> & B2,
  16. Eigen::PlainObjectBase<Derivedleaf> & leaf)
  17. {
  18. using Scalar = typename DerivedPB::Scalar;
  19. using VectorXS = Eigen::Matrix<Scalar, Eigen::Dynamic, 1>;
  20. // Number of primitives
  21. const int m = PB1.rows();
  22. assert(PB1.rows() == PB2.rows());
  23. if(m==0)
  24. {
  25. B1.resize(0,PB1.cols());
  26. B2.resize(0,PB2.cols());
  27. leaf.resize(0);
  28. return;
  29. }
  30. const PlainMatrix<DerivedPB> PBC = (PB1 + PB2) / 2;
  31. const int complete_m = 1 << ((int)std::ceil(std::log2(m))+1);
  32. B1.resize(complete_m, PB1.cols());
  33. B2.resize(complete_m, PB2.cols());
  34. leaf.resize(complete_m);
  35. leaf.setConstant(-2);
  36. std::vector<int> I(m); for(int i = 0; i < m; i++) { I[i] = i; }
  37. std::function<void(const int, const std::vector<int> &)> recursive_helper;
  38. recursive_helper = [&](const int i, const std::vector<int> & I)
  39. {
  40. if(I.size() == 0) { return; }
  41. B1.row(i) = PB1(I, Eigen::all).colwise().minCoeff();
  42. B2.row(i) = PB2(I, Eigen::all).colwise().maxCoeff();
  43. if(I.size() == 1) { leaf(i) = I[0]; return; }
  44. leaf(i) = -1;
  45. int dir;
  46. (B2.row(i) - B1.row(i)).maxCoeff(&dir);
  47. Scalar split_value;
  48. VectorXS Z = PBC(I, dir);
  49. igl::median(Z,split_value);
  50. std::vector<int> left; left.reserve(I.size()/2+1);
  51. std::vector<int> right; right.reserve(I.size()/2+1);
  52. for(int j = 0; j < (int)I.size(); j++)
  53. {
  54. if(Z(j) < split_value)
  55. {
  56. left.push_back(I[j]);
  57. }else if(Z(j) > split_value)
  58. {
  59. right.push_back(I[j]);
  60. }
  61. }
  62. for(int j = 0; j < (int)I.size(); j++)
  63. {
  64. if(Z(j) == split_value)
  65. {
  66. (left.size()<right.size() ? left : right).push_back(I[j]);
  67. }
  68. }
  69. assert(std::abs(int(left.size()-right.size())) <= 1);
  70. const int left_i = 2*i + 1;
  71. const int right_i = 2*i + 2;
  72. recursive_helper(left_i, left);
  73. recursive_helper(right_i, right);
  74. };
  75. recursive_helper(0,I);
  76. }
  77. #ifdef IGL_STATIC_LIBRARY
  78. // Explicit template instantiation
  79. // generated by autoexplicit.sh
  80. template void igl::eytzinger_aabb<Eigen::Matrix<double, -1, 3, 1, -1, 3>, Eigen::Matrix<double, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1>>(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 1, -1, 3>> const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 1, -1, 3>> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 1, -1, 3>>&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 1, -1, 3>>&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>>&);
  81. template void igl::eytzinger_aabb<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1>>(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3>> const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3>> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3>>&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3>>&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>>&);
  82. #endif