build_octree.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. #include "build_octree.h"
  2. #include <vector>
  3. #include <queue>
  4. namespace igl {
  5. template <typename DerivedP, typename IndexType, typename CentersType,
  6. typename WidthsType>
  7. IGL_INLINE void build_octree(const Eigen::MatrixBase<DerivedP>& P,
  8. std::vector<std::vector<IndexType> > & point_indices,
  9. std::vector<Eigen::Matrix<IndexType,8,1>,
  10. Eigen::aligned_allocator<Eigen::Matrix<IndexType,8,1> > > & children,
  11. std::vector<Eigen::Matrix<CentersType,1,3>,
  12. Eigen::aligned_allocator<Eigen::Matrix<CentersType,1,3> > > & centers,
  13. std::vector<WidthsType> & widths)
  14. {
  15. const int MAX_DEPTH = 30000;
  16. typedef Eigen::Matrix<IndexType,8,1> Vector8i;
  17. typedef Eigen::Matrix<typename DerivedP::Scalar, 1, 3> RowVector3PType;
  18. typedef Eigen::Matrix<CentersType, 1, 3> RowVector3CentersType;
  19. auto get_octant = [](RowVector3PType location,
  20. RowVector3CentersType center){
  21. // We use a binary numbering of children. Treating the parent cell's
  22. // center as the origin, we number the octants in the following manner:
  23. // The first bit is 1 iff the octant's x coordinate is positive
  24. // The second bit is 1 iff the octant's y coordinate is positive
  25. // The third bit is 1 iff the octant's z coordinate is positive
  26. //
  27. // For example, the octant with negative x, positive y, positive z is:
  28. // 110 binary = 6 decimal
  29. IndexType index = 0;
  30. if( location(0) >= center(0)){
  31. index = index + 1;
  32. }
  33. if( location(1) >= center(1)){
  34. index = index + 2;
  35. }
  36. if( location(2) >= center(2)){
  37. index = index + 4;
  38. }
  39. return index;
  40. };
  41. auto translate_center = [](const RowVector3CentersType & parent_center,
  42. const CentersType h,
  43. const IndexType child_index){
  44. RowVector3CentersType change_vector;
  45. change_vector << -h,-h,-h;
  46. //positive x chilren are 1,3,4,7
  47. if(child_index % 2){
  48. change_vector(0) = h;
  49. }
  50. //positive y children are 2,3,6,7
  51. if(child_index == 2 || child_index == 3 ||
  52. child_index == 6 || child_index == 7){
  53. change_vector(1) = h;
  54. }
  55. //positive z children are 4,5,6,7
  56. if(child_index > 3){
  57. change_vector(2) = h;
  58. }
  59. return parent_center + change_vector;
  60. };
  61. // How many cells do we have so far?
  62. IndexType m = 0;
  63. // Useful list of number 0..7
  64. const Vector8i zero_to_seven = (Vector8i()<<0,1,2,3,4,5,6,7).finished();
  65. const Vector8i neg_ones = (Vector8i()<<-1,-1,-1,-1,-1,-1,-1,-1).finished();
  66. std::function< void(const int, const int) > helper;
  67. helper = [&helper,&translate_center,&get_octant,&m,
  68. &zero_to_seven,&neg_ones,&P,
  69. &point_indices,&children,&centers,&widths]
  70. (const IndexType index, const int depth)-> void
  71. {
  72. if(point_indices.at(index).size() > 1 && depth < MAX_DEPTH){
  73. //give the parent access to the children
  74. children.at(index) = zero_to_seven.array() + m;
  75. //make the children's data in our arrays
  76. //Add the children to the lists, as default children
  77. WidthsType h = widths.at(index)/2;
  78. RowVector3CentersType curr_center = centers.at(index);
  79. for(int i = 0; i < 8; i++){
  80. children.emplace_back(neg_ones);
  81. point_indices.emplace_back(std::vector<IndexType>());
  82. centers.emplace_back(translate_center(curr_center,h,i));
  83. widths.emplace_back(h);
  84. }
  85. //Split up the points into the corresponding children
  86. for(int j = 0; j < point_indices.at(index).size(); j++){
  87. IndexType curr_point_index = point_indices.at(index).at(j);
  88. IndexType cell_of_curr_point =
  89. get_octant(P.row(curr_point_index),curr_center)+m;
  90. point_indices.at(cell_of_curr_point).emplace_back(curr_point_index);
  91. }
  92. //Now increase m
  93. m += 8;
  94. // Look ma, I'm calling myself.
  95. for(int i = 0; i < 8; i++){
  96. helper(children.at(index)(i),depth+1);
  97. }
  98. }
  99. };
  100. {
  101. std::vector<IndexType> all(P.rows());
  102. for(IndexType i = 0;i<all.size();i++) all[i]=i;
  103. point_indices.emplace_back(all);
  104. }
  105. children.emplace_back(neg_ones);
  106. //Get the minimum AABB for the points
  107. RowVector3PType backleftbottom(P.col(0).minCoeff(),
  108. P.col(1).minCoeff(),
  109. P.col(2).minCoeff());
  110. RowVector3PType frontrighttop(P.col(0).maxCoeff(),
  111. P.col(1).maxCoeff(),
  112. P.col(2).maxCoeff());
  113. RowVector3CentersType aabb_center = (backleftbottom+frontrighttop)/2.0;
  114. WidthsType aabb_width = std::max(std::max(
  115. frontrighttop(0) - backleftbottom(0),
  116. frontrighttop(1) - backleftbottom(1)),
  117. frontrighttop(2) - backleftbottom(2));
  118. centers.emplace_back( aabb_center );
  119. //Widths are the side length of the cube, (not half the side length):
  120. widths.emplace_back( aabb_width );
  121. m++;
  122. // then you have to actually call the function
  123. helper(0,0);
  124. }
  125. }