00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
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
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
00095 float half_root_side = static_cast<float> (0.5f*pow (2.0, tree_levels_)*voxel_size);
00096
00097
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
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
00122 PointXYZ min, max;
00123 getMinMax3D(points, min, max);
00124
00125
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
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
00144 for ( i = 0 ; i < num_points ; ++i )
00145 {
00146
00147 node = this->createLeaf (points[i].x, points[i].y, points[i].z);
00148
00149
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
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
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
00171 (*it)->getData ()->computeAveragePoint ();
00172
00173
00174 normal_length = aux::length3 ((*it)->getData ()->getNormal ());
00175
00176
00177
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
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
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
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
00222 children_[0].setBounds(bounds);
00223 children_[0].setCenter(center);
00224
00225
00226 bounds[4] = center_[2]; bounds[5] = bounds_[5];
00227
00228 center[2] += childside;
00229
00230 children_[1].setBounds(bounds);
00231 children_[1].setCenter(center);
00232
00233
00234 bounds[2] = center_[1]; bounds[3] = bounds_[3];
00235
00236 center[1] += childside;
00237
00238 children_[3].setBounds(bounds);
00239 children_[3].setCenter(center);
00240
00241
00242 bounds[4] = bounds_[4]; bounds[5] = center_[2];
00243
00244 center[2] -= childside;
00245
00246 children_[2].setBounds(bounds);
00247 children_[2].setCenter(center);
00248
00249
00250 bounds[0] = center_[0]; bounds[1] = bounds_[1];
00251
00252 center[0] += childside;
00253
00254 children_[6].setBounds(bounds);
00255 children_[6].setCenter(center);
00256
00257
00258 bounds[4] = center_[2]; bounds[5] = bounds_[5];
00259
00260 center[2] += childside;
00261
00262 children_[7].setBounds(bounds);
00263 children_[7].setCenter(center);
00264
00265
00266 bounds[2] = bounds_[2]; bounds[3] = center_[1];
00267
00268 center[1] -= childside;
00269
00270 children_[5].setBounds(bounds);
00271 children_[5].setCenter(center);
00272
00273
00274 bounds[4] = bounds_[4]; bounds[5] = center_[2];
00275
00276 center[2] -= childside;
00277
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
00305 node = nodes.back ();
00306
00307 nodes.pop_back ();
00308
00309
00310 if ( fabs (radius - aux::distance3<float> (p, node->getCenter ())) <= node->getRadius () )
00311 {
00312
00313 if ( node->hasChildren () )
00314 {
00315 for ( i = 0 ; i < 8 ; ++i )
00316 {
00317 child = node->getChild (i);
00318
00319 if ( child->hasData () || child->hasChildren () )
00320 nodes.push_back (child);
00321 }
00322 }
00323 else if ( node->hasData () )
00324 out.push_back (node);
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
00345 ORROctree::Node *node = nodes.back ();
00346
00347 nodes.pop_back ();
00348
00349
00350 if ( fabs (radius - aux::distance3<float> (p, node->getCenter ())) <= node->getRadius () )
00351 {
00352
00353 if ( node->hasChildren () )
00354 {
00355
00356 for ( int i = 0 ; i < 8 ; ++i )
00357 tmp_ids.push_back (i);
00358
00359
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
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
00389 while ( parent )
00390 {
00391 children = parent->getChildren ();
00392
00393 for ( i = 0 ; i < 8 ; ++i )
00394 {
00395 if ( children[i].hasData () || children[i].hasChildren () )
00396 break;
00397 }
00398
00399
00400 if ( i == 8 )
00401 {
00402 parent->deleteChildren ();
00403 parent->deleteData ();
00404
00405 parent = parent->getParent ();
00406 }
00407 else
00408
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
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
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