void Octree::getFullLeafsNearPlane(const double* p, const double* n, double dist, list<OctreeNode*>& out) { list<OctreeNode*> nodes; nodes.push_back(mRoot); int i; while ( nodes.size() ) { // Get the last element in the list OctreeNode* node = nodes.back(); // Remove the last element from the list nodes.pop_back(); // Check if the sphere intersects the current node if ( fabs(Vector::signedDistToPlane3(p, n, node->getCenter())) <= dist + node->getVoxelRadius() ) { // We have an intersection -> push back the children of the current node if ( node->hasChildren() ) { for ( i = 0 ; i < 8 ; ++i ) nodes.push_back(node->getChild(i)); } else if ( node->isFull() ) out.push_back(node); } } }
void Octree::getFullLeafsWithinSphere(double* p, double radius, list<OctreeNode*>& out) { list<OctreeNode*> nodes; nodes.push_back(mRoot); int i; double nodeCenterToSphereCenterDist; while ( nodes.size() ) { // Get the last element in the list OctreeNode* node = nodes.back(); // Remove the last element from the list nodes.pop_back(); // Get the distance between the node center and the sphere center nodeCenterToSphereCenterDist = Vector::dist3(p, node->getCenter()); // Check if the current node is completely contained in the sphere. // If yes -> add all its full children to 'out'. if ( nodeCenterToSphereCenterDist + node->getVoxelRadius() <= radius ) this->pushBackFullLeafsFromNode(node, out); // Check if the sphere intersects the current node else if ( fabs(radius - nodeCenterToSphereCenterDist) <= node->getVoxelRadius() ) { // We have an intersection -> push back the children of the current node if ( node->hasChildren() ) for ( i = 0 ; i < 8 ; ++i ) nodes.push_back(node->getChild(i)); else if ( node->isFull() ) out.push_back(node); } } }
void Octree::buildFullLeafsVectorAndNeighbourhoodStructure() { if ( !mRoot ) return; int i; OctreeNode* node; list<OctreeNode*> nodes; // Init nodes.push_back(mRoot); mFullLeafs.clear(); mBoundsOfFullLeafs[0] = mBounds[1]; // set min x to the max x of the whole tree mBoundsOfFullLeafs[1] = mBounds[0]; // set max x to the min x of the whole tree mBoundsOfFullLeafs[2] = mBounds[3]; // ... mBoundsOfFullLeafs[3] = mBounds[2]; mBoundsOfFullLeafs[4] = mBounds[5]; mBoundsOfFullLeafs[5] = mBounds[4]; while ( nodes.size() ) { node = nodes.back(); nodes.pop_back(); if ( node->hasChildren() ) for ( i = 0 ; i < 8 ; ++i ) nodes.push_back(node->getChild(i)); else if ( node->hasData() ) { if ( node->getBounds()[0] < mBoundsOfFullLeafs[0] ) mBoundsOfFullLeafs[0] = node->getBounds()[0]; if ( node->getBounds()[2] < mBoundsOfFullLeafs[2] ) mBoundsOfFullLeafs[2] = node->getBounds()[2]; if ( node->getBounds()[4] < mBoundsOfFullLeafs[4] ) mBoundsOfFullLeafs[4] = node->getBounds()[4]; if ( node->getBounds()[1] > mBoundsOfFullLeafs[1] ) mBoundsOfFullLeafs[1] = node->getBounds()[1]; if ( node->getBounds()[3] > mBoundsOfFullLeafs[3] ) mBoundsOfFullLeafs[3] = node->getBounds()[3]; if ( node->getBounds()[5] > mBoundsOfFullLeafs[5] ) mBoundsOfFullLeafs[5] = node->getBounds()[5]; mFullLeafs.push_back(node); this->collectFullNeighbours(node); } } this->sortFullLeafsVector(); }
void Octree::getFullLeafsInRange(double* p, double r1, double r2, list<OctreeNode*>& out) { list<OctreeNode*> nodes; nodes.push_back(mRoot); int i; double d1, d2, dist; while ( nodes.size() ) { // Get the last element in the list OctreeNode* node = nodes.back(); // Remove the last element in the list nodes.pop_back(); #ifdef OCTREE_TEST_MODE ++mNodeRangeTestCounter; #endif // Get the distance between the sphere radius and the node center dist = Vector::dist3(p, node->getCenter()); d1 = dist + node->getVoxelRadius(); d2 = dist - node->getVoxelRadius(); if ( d1 >= r1 && d2 <= r2 ) { // Check if we have the special case that the voxel is completely between both spheres if ( d1 <= r2 && d2 >= r1 ) this->pushBackFullLeafsFromNode(node, out); else { if ( node->hasChildren() ) { // Push back the children for further processing for ( i = 0 ; i < 8 ; ++i ) nodes.push_back(node->getChild(i)); } // We have reached a leaf -> save it in 'out' if it's full else if ( node->isFull() ) out.push_back(node); } } } }
OctreeNode* Octree::getRandomFullLeafOnSphere(const double* p, double radius) const { list<OctreeNode*> nodes; nodes.push_back(mRoot); int i, rand_id; vector<int> tmp_ids; tmp_ids.reserve(8); while ( nodes.size() ) { // Get the last element in the list OctreeNode* node = nodes.back(); // Remove the last element from the list nodes.pop_back(); // Check if the sphere intersects the current node if ( fabs(radius - Vector::dist3(p, node->getCenter())) <= node->getVoxelRadius() ) { // We have an intersection -> push back the children of the current node if ( node->hasChildren() ) { // Prepare the tmp id vector for ( i = 0 ; i < 8 ; ++i ) tmp_ids.push_back(i); // Push back the children in random order for ( i = 0 ; i < 8 ; ++i ) { rand_id = mRandGen.getRandomInteger(0, tmp_ids.size()-1); nodes.push_back(node->getChild(tmp_ids[rand_id])); // Remove the randomly selected id tmp_ids.erase(tmp_ids.begin() + rand_id); } } else if ( node->isFull() ) return node; } } return NULL; }
void Octree::buildNeighbourhoodStructure() { if ( !mRoot ) return; int i; OctreeNode* node; list<OctreeNode*> nodes; nodes.push_back(mRoot); while ( nodes.size() ) { node = nodes.back(); nodes.pop_back(); if ( node->hasChildren() ) for ( i = 0 ; i < 8 ; ++i ) nodes.push_back(node->getChild(i)); else if ( node->hasData() ) this->collectFullNeighbours(node); } }
OctreeNode* Octree::getRandomFullLeaf() { list<OctreeNode*> nodes; nodes.push_back(mRoot); int i, rand_id; vector<int> tmp_ids; tmp_ids.reserve(8); while ( nodes.size() ) { // Get the last element in the list OctreeNode* node = nodes.back(); // Remove the last element from the list nodes.pop_back(); // Push back the children of the current node if ( node->hasChildren() ) { // Prepare the tmp id vector for ( i = 0 ; i < 8 ; ++i ) tmp_ids.push_back(i); // Push back the children in random order for ( i = 0 ; i < 8 ; ++i ) { rand_id = mRandGen.getRandomInteger(0, tmp_ids.size()-1); nodes.push_back(node->getChild(tmp_ids[rand_id])); // Remove the randomly selected id tmp_ids.erase(tmp_ids.begin() + rand_id); } } else if ( node->isFull() ) return node; } return NULL; }