octree.cpp 7.2 KB

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