orr_octree.cpp
Go to the documentation of this file.
00001 /*
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Point Cloud Library (PCL) - www.pointclouds.org
00005  *  Copyright (c) 2010-2012, Willow Garage, Inc.
00006  *
00007  *  All rights reserved.
00008  *
00009  *  Redistribution and use in source and binary forms, with or without
00010  *  modification, are permitted provided that the following conditions
00011  *  are met:
00012  *
00013  *   * Redistributions of source code must retain the above copyright
00014  *     notice, this list of conditions and the following disclaimer.
00015  *   * Redistributions in binary form must reproduce the above
00016  *     copyright notice, this list of conditions and the following
00017  *     disclaimer in the documentation and/or other materials provided
00018  *     with the distribution.
00019  *   * Neither the name of Willow Garage, Inc. nor the names of its
00020  *     contributors may be used to endorse or promote products derived
00021  *     from this software without specific prior written permission.
00022  *
00023  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00024  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00025  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00026  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00027  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00028  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00029  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00030  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00031  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00032  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00033  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00034  *  POSSIBILITY OF SUCH DAMAGE.
00035  *
00036  * $Id$
00037  *
00038  */
00039 
00040 #include <pcl/recognition/ransac_based/orr_octree.h>
00041 #include <pcl/common/common.h>
00042 #include <pcl/common/random.h>
00043 #include <cstdlib>
00044 #include <cmath>
00045 #include <algorithm>
00046 #include <list>
00047 
00048 using namespace std;
00049 using namespace pcl::recognition;
00050 
00051 pcl::recognition::ORROctree::ORROctree ()
00052 : voxel_size_ (-1.0),
00053   tree_levels_ (-1),
00054   root_ (NULL)
00055 {
00056 }
00057 
00058 //================================================================================================================================================================
00059 
00060 void
00061 pcl::recognition::ORROctree::clear ()
00062 {
00063   if ( root_ )
00064   {
00065     delete root_;
00066     root_ = NULL;
00067   }
00068 
00069   full_leaves_.clear();
00070 }
00071 
00072 //================================================================================================================================================================
00073 
00074 void
00075 pcl::recognition::ORROctree::build (const float* bounds, float voxel_size)
00076 {
00077   if ( voxel_size <= 0.0f )
00078     return;
00079 
00080   this->clear();
00081 
00082   voxel_size_ = voxel_size;
00083 
00084   float extent = std::max (std::max (bounds[1]-bounds[0], bounds[3]-bounds[2]), bounds[5]-bounds[4]);
00085   float center[3] = {0.5f*(bounds[0]+bounds[1]), 0.5f*(bounds[2]+bounds[3]), 0.5f*(bounds[4]+bounds[5])};
00086   float arg = extent/voxel_size;
00087 
00088   // Compute the number of tree levels
00089   if ( arg > 1.0f )
00090     tree_levels_ = static_cast<int> (ceil (log (arg)/log (2.0)) + 0.5);
00091   else
00092     tree_levels_ = 0;
00093 
00094   // Compute the number of octree levels and the bounds of the root
00095   float half_root_side = static_cast<float> (0.5f*pow (2.0, tree_levels_)*voxel_size);
00096 
00097   // Determine the bounding box of the octree
00098   bounds_[0] = center[0] - half_root_side;
00099   bounds_[1] = center[0] + half_root_side;
00100   bounds_[2] = center[1] - half_root_side;
00101   bounds_[3] = center[1] + half_root_side;
00102   bounds_[4] = center[2] - half_root_side;
00103   bounds_[5] = center[2] + half_root_side;
00104 
00105   // Create and initialize the root
00106   root_ = new ORROctree::Node();
00107   root_->setCenter(center);
00108   root_->setBounds(bounds_);
00109   root_->setParent(NULL);
00110   root_->computeRadius();
00111 }
00112 
00113 //================================================================================================================================================================
00114 
00115 void
00116 pcl::recognition::ORROctree::build (const PointCloudIn& points, float voxel_size, const PointCloudN* normals, float enlarge_bounds)
00117 {
00118   if ( voxel_size <= 0.0f )
00119     return;
00120 
00121   // Get the bounds of the input point set
00122   PointXYZ min, max;
00123   getMinMax3D(points, min, max);
00124 
00125   // Enlarge the bounds a bit to avoid points lying exact on the octree boundaries
00126   float eps = enlarge_bounds*std::max (std::max (max.x-min.x, max.y-min.y), max.z-min.z);
00127   float b[6] = {min.x-eps, max.x+eps, min.y-eps, max.y+eps, min.z-eps, max.z+eps};
00128 
00129   // Build an empty octree with the right boundaries and the right number of levels
00130   this->build (b, voxel_size);
00131 
00132 #ifdef PCL_REC_ORR_OCTREE_VERBOSE
00133   printf("ORROctree::%s(): start\n", __func__);
00134   printf("point set bounds =\n"
00135          "[%f, %f]\n"
00136          "[%f, %f]\n"
00137          "[%f, %f]\n", min.x, max.x, min.y, max.y, min.z, max.z);
00138 #endif
00139 
00140   int i, num_points = static_cast<int> (points.size ());
00141   ORROctree::Node* node;
00142 
00143   // Fill the leaves with the points
00144   for ( i = 0 ; i < num_points ; ++i )
00145   {
00146     // Create a leaf which contains the i-th point.
00147     node = this->createLeaf (points[i].x, points[i].y, points[i].z);
00148 
00149     // Make sure that the point is within some leaf
00150     if ( !node )
00151     {
00152       fprintf (stderr, "WARNING in 'ORROctree::%s()': the point (%f, %f, %f) should be within the octree bounds!\n",
00153         __func__, points[i].x, points[i].y, points[i].z);
00154       continue;
00155     }
00156 
00157     // Now, that we have the right leaf -> fill it
00158     node->getData ()->addToPoint (points[i].x, points[i].y, points[i].z);
00159     if ( normals )
00160       node->getData ()->addToNormal (normals->at(i).normal_x, normals->at(i).normal_y, normals->at(i).normal_z);
00161   }
00162 
00163   // Compute the normals and average points for each full octree node
00164   if ( normals )
00165   {
00166     float normal_length;
00167 
00168     for ( vector<ORROctree::Node*>::iterator it = full_leaves_.begin() ; it != full_leaves_.end() ; )
00169     {
00170       // Compute the average point in the current octree leaf
00171       (*it)->getData ()->computeAveragePoint ();
00172 
00173       // Compute the length of the average normal
00174       normal_length = aux::length3 ((*it)->getData ()->getNormal ());
00175 
00176       // We are suppose to use normals. However, it could be that all normals in this leaf are "illegal", because,
00177       // e.g., they were not available in the data set. In this case, remove the leaf from the octree.
00178       if ( normal_length <= numeric_limits<float>::epsilon () )
00179       {
00180         this->deleteBranch (*it);
00181         it = full_leaves_.erase (it);
00182       }
00183       else
00184       {
00185         aux::mult3 ((*it)->getData ()->getNormal (), 1.0f/normal_length);
00186         ++it;
00187       }
00188     }
00189   }
00190   else
00191   {
00192     // Iterate over all full leaves and average points
00193     for ( vector<ORROctree::Node*>::iterator it = full_leaves_.begin() ; it != full_leaves_.end() ; ++it )
00194       (*it)->getData ()->computeAveragePoint ();
00195   }
00196 
00197 #ifdef PCL_REC_ORR_OCTREE_VERBOSE
00198   printf("ORROctree::%s(): end\n", __func__);
00199 #endif
00200 }
00201 
00202 //================================================================================================================================================================
00203 
00204 bool
00205 pcl::recognition::ORROctree::Node::createChildren()
00206 {
00207   if ( children_ )
00208     return (false);
00209 
00210   float bounds[6], center[3], childside = 0.5f*(bounds_[1]-bounds_[0]);
00211   children_ = new ORROctree::Node[8];
00212 
00213   // Compute bounds and center for child 0, i.e., for (0,0,0)
00214   bounds[0] = bounds_[0]; bounds[1] = center_[0];
00215   bounds[2] = bounds_[2]; bounds[3] = center_[1];
00216   bounds[4] = bounds_[4]; bounds[5] = center_[2];
00217   // Compute the center of the new child
00218   center[0] = 0.5f*(bounds[0] + bounds[1]);
00219   center[1] = 0.5f*(bounds[2] + bounds[3]);
00220   center[2] = 0.5f*(bounds[4] + bounds[5]);
00221   // Save the results
00222   children_[0].setBounds(bounds);
00223   children_[0].setCenter(center);
00224 
00225   // Compute bounds and center for child 1, i.e., for (0,0,1)
00226   bounds[4] = center_[2]; bounds[5] = bounds_[5];
00227   // Update the center
00228   center[2] += childside;
00229   // Save the results
00230   children_[1].setBounds(bounds);
00231   children_[1].setCenter(center);
00232 
00233   // Compute bounds and center for child 3, i.e., for (0,1,1)
00234   bounds[2] = center_[1]; bounds[3] = bounds_[3];
00235   // Update the center
00236   center[1] += childside;
00237   // Save the results
00238   children_[3].setBounds(bounds);
00239   children_[3].setCenter(center);
00240 
00241   // Compute bounds and center for child 2, i.e., for (0,1,0)
00242   bounds[4] = bounds_[4]; bounds[5] = center_[2];
00243   // Update the center
00244   center[2] -= childside;
00245   // Save the results
00246   children_[2].setBounds(bounds);
00247   children_[2].setCenter(center);
00248 
00249   // Compute bounds and center for child 6, i.e., for (1,1,0)
00250   bounds[0] = center_[0]; bounds[1] = bounds_[1];
00251   // Update the center
00252   center[0] += childside;
00253   // Save the results
00254   children_[6].setBounds(bounds);
00255   children_[6].setCenter(center);
00256 
00257   // Compute bounds and center for child 7, i.e., for (1,1,1)
00258   bounds[4] = center_[2]; bounds[5] = bounds_[5];
00259   // Update the center
00260   center[2] += childside;
00261   // Save the results
00262   children_[7].setBounds(bounds);
00263   children_[7].setCenter(center);
00264 
00265   // Compute bounds and center for child 5, i.e., for (1,0,1)
00266   bounds[2] = bounds_[2]; bounds[3] = center_[1];
00267   // Update the center
00268   center[1] -= childside;
00269   // Save the results
00270   children_[5].setBounds(bounds);
00271   children_[5].setCenter(center);
00272 
00273   // Compute bounds and center for child 4, i.e., for (1,0,0)
00274   bounds[4] = bounds_[4]; bounds[5] = center_[2];
00275   // Update the center
00276   center[2] -= childside;
00277   // Save the results
00278   children_[4].setBounds(bounds);
00279   children_[4].setCenter(center);
00280 
00281   for ( int i = 0 ; i < 8 ; ++i )
00282   {
00283     children_[i].computeRadius();
00284     children_[i].setParent(this);
00285   }
00286 
00287   return (true);
00288 }
00289 
00290 //====================================================================================================
00291 
00292 void
00293 pcl::recognition::ORROctree::getFullLeavesIntersectedBySphere (const float* p, float radius, std::list<ORROctree::Node*>& out) const
00294 {
00295   list<ORROctree::Node*> nodes;
00296   nodes.push_back (root_);
00297 
00298   ORROctree::Node *node, *child;
00299 
00300   int i;
00301 
00302   while ( !nodes.empty () )
00303   {
00304     // Get the last element in the list
00305     node = nodes.back ();
00306     // Remove the last element from the list
00307     nodes.pop_back ();
00308 
00309     // Check if the sphere intersects the current node
00310     if ( fabs (radius - aux::distance3<float> (p, node->getCenter ())) <= node->getRadius () )
00311     {
00312       // We have an intersection -> push back the children of the current node
00313       if ( node->hasChildren () )
00314       {
00315         for ( i = 0 ; i < 8 ; ++i )
00316         {
00317           child = node->getChild (i);
00318           // We do not want to push all children -> only leaves or children with children
00319           if ( child->hasData () || child->hasChildren () )
00320             nodes.push_back (child);
00321         }
00322       }
00323       else if ( node->hasData () )
00324         out.push_back (node); // We got a full leaf
00325     }
00326   }
00327 }
00328 
00329 //================================================================================================================================================================
00330 
00331 ORROctree::Node*
00332 pcl::recognition::ORROctree::getRandomFullLeafOnSphere (const float* p, float radius) const
00333 {
00334   vector<int> tmp_ids;
00335   tmp_ids.reserve (8);
00336 
00337   pcl::common::UniformGenerator<int> randgen (0, 1, static_cast<uint32_t> (time (NULL)));
00338 
00339   list<ORROctree::Node*> nodes;
00340   nodes.push_back (root_);
00341 
00342   while ( !nodes.empty () )
00343   {
00344     // Get the last element in the list
00345     ORROctree::Node *node = nodes.back ();
00346     // Remove the last element from the list
00347     nodes.pop_back ();
00348 
00349     // Check if the sphere intersects the current node
00350     if ( fabs (radius - aux::distance3<float> (p, node->getCenter ())) <= node->getRadius () )
00351     {
00352       // We have an intersection -> push back the children of the current node
00353       if ( node->hasChildren () )
00354       {
00355         // Prepare the tmp id vector
00356         for ( int i = 0 ; i < 8 ; ++i )
00357           tmp_ids.push_back (i);
00358 
00359         // Push back the children in random order
00360         for ( int i = 0 ; i < 8 ; ++i )
00361         {
00362           randgen.setParameters (0, static_cast<int> (tmp_ids.size ()) - 1);
00363           int rand_pos = randgen.run ();
00364           nodes.push_back (node->getChild (tmp_ids[rand_pos]));
00365           // Remove the randomly selected id
00366           tmp_ids.erase (tmp_ids.begin () + rand_pos);
00367         }
00368       }
00369       else if ( node->hasData () )
00370         return node;
00371     }
00372   }
00373 
00374   return NULL;
00375 }
00376 
00377 //================================================================================================================================================================
00378 
00379 void
00380 pcl::recognition::ORROctree::deleteBranch (Node* node)
00381 {
00382   node->deleteChildren ();
00383   node->deleteData ();
00384 
00385   Node *children, *parent = node->getParent ();
00386   int i;
00387 
00388   // Go up until you reach a node which has other non-empty children (i.e., children with other children or with data)
00389   while ( parent )
00390   {
00391     children = parent->getChildren ();
00392     // Check the children
00393         for ( i = 0 ; i < 8 ; ++i )
00394     {
00395       if ( children[i].hasData () || children[i].hasChildren () )
00396         break;
00397     }
00398 
00399         // There are no children with other children or with data -> delete them all!
00400         if ( i == 8 )
00401     {
00402       parent->deleteChildren ();
00403       parent->deleteData ();
00404       // Go one level up
00405       parent = parent->getParent ();
00406     }
00407         else
00408       // Terminate the deleting process
00409       break;
00410   }
00411 }
00412 
00413 //================================================================================================================================================================
00414 
00415 void
00416 pcl::recognition::ORROctree::getFullLeavesPoints (PointCloudOut& out) const
00417 {
00418   out.resize(full_leaves_.size ());
00419   size_t i = 0;
00420 
00421   // Now iterate over all full leaves and compute the normals and average points
00422   for ( vector<ORROctree::Node*>::const_iterator it = full_leaves_.begin() ; it != full_leaves_.end() ; ++it, ++i )
00423   {
00424     out[i].x = (*it)->getData ()->getPoint ()[0];
00425     out[i].y = (*it)->getData ()->getPoint ()[1];
00426     out[i].z = (*it)->getData ()->getPoint ()[2];
00427   }
00428 }
00429 
00430 //================================================================================================================================================================
00431 
00432 void
00433 pcl::recognition::ORROctree::getNormalsOfFullLeaves (PointCloudN& out) const
00434 {
00435   out.resize(full_leaves_.size ());
00436   size_t i = 0;
00437 
00438   // Now iterate over all full leaves and compute the normals and average points
00439   for ( vector<ORROctree::Node*>::const_iterator it = full_leaves_.begin() ; it != full_leaves_.end() ; ++it, ++i )
00440   {
00441     out[i].normal_x = (*it)->getData ()->getNormal ()[0];
00442     out[i].normal_y = (*it)->getData ()->getNormal ()[1];
00443     out[i].normal_z = (*it)->getData ()->getNormal ()[2];
00444   }
00445 }
00446 
00447 //================================================================================================================================================================


pcl
Author(s): Open Perception
autogenerated on Wed Aug 26 2015 15:27:30