knn_octree.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. #include "point_areas_and_normals.h"
  2. #include <cmath>
  3. #include <igl/parallel_for.h>
  4. double distance_to_width_one_cube(Eigen::RowVector3d point){
  5. return std::sqrt(std::pow(std::max(std::abs(point(0))-1,0.0),2)
  6. + std::pow(std::max(std::abs(point(1))-1,0.0),2)
  7. + std::pow(std::max(std::abs(point(2))-1,0.0),2));
  8. }
  9. double distance_to_cube(Eigen::RowVector3d point, Eigen::RowVector3d cube_center, double cube_width){
  10. Eigen::RowVector3d transformed_point = (point-cube_center)/cube_width;
  11. return cube_width*distance_to_width_one_cube(transformed_point);
  12. }
  13. // template <typename DerivedP, typename DerivedI, typename DerivedO>
  14. // IGL_INLINE void point_areas_and_normals(
  15. // const Eigen::MatrixBase<DerivedP>& P,
  16. // const Eigen::MatrixBase<DerivedI>& I,
  17. // const Eigen::MatrixBase<DerivedO>& O,
  18. // Eigen::MatrixBase<DerivedA> & A,
  19. // Eigen::MatrixBase<DerivedN> & N);
  20. namespace igl {
  21. void knn_octree(const Eigen::MatrixXd & P,
  22. const int & k,
  23. const std::vector<std::vector<int> > & point_indices,
  24. const std::vector<Eigen::Matrix<int,8,1>, Eigen::aligned_allocator<Eigen::Matrix<int,8,1>>> & children,
  25. const std::vector<Eigen::RowVector3d, Eigen::aligned_allocator<Eigen::RowVector3d>> & centers,
  26. const std::vector<double> & widths,
  27. Eigen::MatrixXi & I
  28. )
  29. {
  30. const int n = P.rows();
  31. const int real_k = std::min(n,k);
  32. I.resize(n,real_k);
  33. igl::parallel_for(n,[&](int i)
  34. {
  35. int points_found = 0;
  36. Eigen::RowVector3d point_of_interest = P.row(i);
  37. //To make my priority queue take both points and octree cells, I use the indices 0 to n-1
  38. //for the n points, and the indices n to n+m-1 for the m octree cells
  39. // Using lambda to compare elements.
  40. auto cmp = [&point_of_interest, &P, &centers, &widths, &n](int left, int right) {
  41. double leftdistance, rightdistance;
  42. if(left < n){ //left is a point index
  43. leftdistance = (P.row(left) - point_of_interest).norm();
  44. } else { //left is an octree cell
  45. leftdistance = distance_to_cube(point_of_interest,centers.at(left-n),widths.at(left-n));
  46. }
  47. if(right < n){ //left is a point index
  48. rightdistance = (P.row(right) - point_of_interest).norm();
  49. } else { //left is an octree cell
  50. rightdistance = distance_to_cube(point_of_interest,centers.at(right-n),widths.at(right-n));
  51. }
  52. return leftdistance >= rightdistance;
  53. };
  54. std::priority_queue<int, std::vector<int>, decltype(cmp)> queue(cmp);
  55. queue.push(n); //This is the 0th octree cell (ie the root)
  56. while(points_found < real_k){
  57. int curr_cell_or_point = queue.top();
  58. queue.pop();
  59. if(curr_cell_or_point < n){ //current index is for is a point
  60. I(i,points_found) = curr_cell_or_point;
  61. points_found++;
  62. } else {
  63. int curr_cell = curr_cell_or_point - n;
  64. if(children.at(curr_cell)(0) == -1){ //In the case of a leaf
  65. if(point_indices.at(curr_cell).size() > 0){ //Assumption: Leaves either have one point, or none
  66. queue.push(point_indices.at(curr_cell).at(0)); //push the point (pardon the pun)
  67. }
  68. } else { //Not a leaf
  69. for(int j = 0; j < 8; j++){
  70. queue.push(children.at(curr_cell)(j)+n); //+n to adjust for the octree cells
  71. }
  72. }
  73. }
  74. }
  75. // points_found = 0;
  76. // std::list<int> l = {n}; //This is the 0th octree cell (ie the root)
  77. // while(points_found < real_k){
  78. // int curr_cell_or_point = l.front();
  79. // l.pop_front();
  80. // if(curr_cell_or_point < n){ //current index is for is a point
  81. // I(i,points_found) = curr_cell_or_point;
  82. // points_found++;
  83. // } else {
  84. // int curr_cell = curr_cell_or_point - n;
  85. // if(children.at(curr_cell)(0) == -1){ //In the case of a leaf
  86. // if(point_indices.at(curr_cell).size() > 0){ //Assumption: Leaves either have one point, or none
  87. // l.emplace_back(point_indices.at(curr_cell).at(0)); //push the point (pardon the pun)
  88. // }
  89. // } else { //Not a leaf
  90. // for(int j = 0; j < 8; j++){
  91. // l.emplace_back(children.at(curr_cell)(j)+n); //+n to adjust for the octree cells
  92. // }
  93. // }
  94. // l.sort(cmp);
  95. // int new_size = std::min<int>(l.size(),real_k-points_found);
  96. // l.resize(new_size);
  97. // }
  98. // }
  99. //
  100. },1000);
  101. }
  102. }