Point Cloud Library (PCL)  1.6.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
octree_pointcloud.hpp
Go to the documentation of this file.
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Point Cloud Library (PCL) - www.pointclouds.org
5  * Copyright (c) 2010-2012, Willow Garage, Inc.
6  *
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * * Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  * * Redistributions in binary form must reproduce the above
16  * copyright notice, this list of conditions and the following
17  * disclaimer in the documentation and/or other materials provided
18  * with the distribution.
19  * * Neither the name of Willow Garage, Inc. nor the names of its
20  * contributors may be used to endorse or promote products derived
21  * from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  *
36  * $Id: octree_pointcloud.hpp 6119 2012-07-03 18:50:04Z aichim $
37  */
38 
39 #ifndef OCTREE_POINTCLOUD_HPP_
40 #define OCTREE_POINTCLOUD_HPP_
41 
42 #include <vector>
43 #include <assert.h>
44 
45 #include <pcl/common/common.h>
46 
48 template<typename PointT, typename LeafT, typename BranchT, typename OctreeT>
50  OctreeT (), input_ (PointCloudConstPtr ()), indices_ (IndicesConstPtr ()),
51  epsilon_ (0), resolution_ (resolution), minX_ (0.0f), maxX_ (resolution), minY_ (0.0f),
52  maxY_ (resolution), minZ_ (0.0f), maxZ_ (resolution), boundingBoxDefined_ (false)
53 {
54  assert (resolution > 0.0f);
55 }
56 
58 template<typename PointT, typename LeafT, typename BranchT, typename OctreeT>
60 {
61 }
62 
64 template<typename PointT, typename LeafT, typename BranchT, typename OctreeT> void
66 {
67  size_t i;
68 
69  assert (this->leafCount_==0);
70  if (indices_)
71  {
72  for (std::vector<int>::const_iterator current = indices_->begin (); current != indices_->end (); ++current)
73  {
74  if (isFinite (input_->points[*current]))
75  {
76  assert( (*current>=0) && (*current < static_cast<int> (input_->points.size ())));
77 
78  // add points to octree
79  this->addPointIdx (*current);
80  }
81  }
82  }
83  else
84  {
85  for (i = 0; i < input_->points.size (); i++)
86  {
87  if (isFinite (input_->points[i]))
88  {
89  // add points to octree
90  this->addPointIdx (static_cast<unsigned int> (i));
91  }
92  }
93  }
94 }
95 
97 template<typename PointT, typename LeafT, typename BranchT, typename OctreeT> void
99 {
100  this->addPointIdx (pointIdx_arg);
101  if (indices_arg)
102  indices_arg->push_back (pointIdx_arg);
103 }
104 
106 template<typename PointT, typename LeafT, typename BranchT, typename OctreeT> void
108 {
109  assert (cloud_arg==input_);
110 
111  cloud_arg->push_back (point_arg);
112 
113  this->addPointIdx (static_cast<const int> (cloud_arg->points.size ()) - 1);
114 }
115 
117 template<typename PointT, typename LeafT, typename BranchT, typename OctreeT> void
119  IndicesPtr indices_arg)
120 {
121  assert (cloud_arg==input_);
122  assert (indices_arg==indices_);
123 
124  cloud_arg->push_back (point_arg);
125 
126  this->addPointFromCloud (static_cast<const int> (cloud_arg->points.size ()) - 1, indices_arg);
127 }
128 
130 template<typename PointT, typename LeafT, typename BranchT, typename OctreeT> bool
132 {
133  OctreeKey key;
134 
135  // generate key for point
136  this->genOctreeKeyforPoint (point_arg, key);
137 
138  // search for key in octree
139  return (isPointWithinBoundingBox (point_arg) && this->existLeaf (key));
140 }
141 
143 template<typename PointT, typename LeafT, typename BranchT, typename OctreeT> bool
145 {
146  // retrieve point from input cloud
147  const PointT& point = this->input_->points[pointIdx_arg];
148 
149  // search for voxel at point in octree
150  return (this->isVoxelOccupiedAtPoint (point));
151 }
152 
154 template<typename PointT, typename LeafT, typename BranchT, typename OctreeT> bool
156  const double pointX_arg, const double pointY_arg, const double pointZ_arg) const
157 {
158  OctreeKey key;
159 
160  // generate key for point
161  this->genOctreeKeyforPoint (pointX_arg, pointY_arg, pointZ_arg, key);
162 
163  return (this->existLeaf (key));
164 }
165 
167 template<typename PointT, typename LeafT, typename BranchT, typename OctreeT> void
169 {
170  OctreeKey key;
171 
172  // generate key for point
173  this->genOctreeKeyforPoint (point_arg, key);
174 
175  this->removeLeaf (key);
176 }
177 
179 template<typename PointT, typename LeafT, typename BranchT, typename OctreeT> void
181 {
182  // retrieve point from input cloud
183  const PointT& point = this->input_->points[pointIdx_arg];
184 
185  // delete leaf at point
186  this->deleteVoxelAtPoint (point);
187 }
188 
190 template<typename PointT, typename LeafT, typename BranchT, typename OctreeT> int
192  AlignedPointTVector &voxelCenterList_arg) const
193 {
194  OctreeKey key;
195  key.x = key.y = key.z = 0;
196 
197  voxelCenterList_arg.clear ();
198 
199  return getOccupiedVoxelCentersRecursive (this->rootNode_, key, voxelCenterList_arg);
200 
201 }
202 
204 template<typename PointT, typename LeafT, typename BranchT, typename OctreeT> int
206  const Eigen::Vector3f& origin,
207  const Eigen::Vector3f& end,
208  AlignedPointTVector &voxel_center_list,
209  float precision)
210 {
211  Eigen::Vector3f direction = end - origin;
212  float norm = direction.norm ();
213  direction.normalize ();
214 
215  const float step_size = static_cast<const float> (resolution_) * precision;
216  // Ensure we get at least one step for the first voxel.
217  const int nsteps = std::max (1, static_cast<int> (norm / step_size));
218 
219  OctreeKey prev_key;
220 
221  bool bkeyDefined = false;
222 
223  // Walk along the line segment with small steps.
224  for (int i = 0; i < nsteps; ++i)
225  {
226  Eigen::Vector3f p = origin + (direction * step_size * static_cast<const float> (i));
227 
228  PointT octree_p;
229  octree_p.x = p.x ();
230  octree_p.y = p.y ();
231  octree_p.z = p.z ();
232 
233  OctreeKey key;
234  this->genOctreeKeyforPoint (octree_p, key);
235 
236  // Not a new key, still the same voxel.
237  if ((key == prev_key) && (bkeyDefined) )
238  continue;
239 
240  prev_key = key;
241  bkeyDefined = true;
242 
243  PointT center;
244  genLeafNodeCenterFromOctreeKey (key, center);
245  voxel_center_list.push_back (center);
246  }
247 
248  OctreeKey end_key;
249  PointT end_p;
250  end_p.x = end.x ();
251  end_p.y = end.y ();
252  end_p.z = end.z ();
253  this->genOctreeKeyforPoint (end_p, end_key);
254  if (!(end_key == prev_key))
255  {
256  PointT center;
257  genLeafNodeCenterFromOctreeKey (end_key, center);
258  voxel_center_list.push_back (center);
259  }
260 
261  return (static_cast<int> (voxel_center_list.size ()));
262 }
263 
265 template<typename PointT, typename LeafT, typename BranchT, typename OctreeT> void
267 {
268 
269  double minX, minY, minZ, maxX, maxY, maxZ;
270 
271  PointT min_pt;
272  PointT max_pt;
273 
274  // bounding box cannot be changed once the octree contains elements
275  assert (this->leafCount_ == 0);
276 
277  pcl::getMinMax3D (*input_, min_pt, max_pt);
278 
279  float minValue = std::numeric_limits<float>::epsilon () * 512.0f;
280 
281  minX = min_pt.x;
282  minY = min_pt.y;
283  minZ = min_pt.z;
284 
285  maxX = max_pt.x + minValue;
286  maxY = max_pt.y + minValue;
287  maxZ = max_pt.z + minValue;
288 
289  // generate bit masks for octree
290  defineBoundingBox (minX, minY, minZ, maxX, maxY, maxZ);
291 }
292 
294 template<typename PointT, typename LeafT, typename BranchT, typename OctreeT> void
296  const double minY_arg,
297  const double minZ_arg,
298  const double maxX_arg,
299  const double maxY_arg,
300  const double maxZ_arg)
301 {
302  // bounding box cannot be changed once the octree contains elements
303  assert (this->leafCount_ == 0);
304 
305  assert (maxX_arg >= minX_arg);
306  assert (maxY_arg >= minY_arg);
307  assert (maxZ_arg >= minZ_arg);
308 
309  minX_ = minX_arg;
310  maxX_ = maxX_arg;
311 
312  minY_ = minY_arg;
313  maxY_ = maxY_arg;
314 
315  minZ_ = minZ_arg;
316  maxZ_ = maxZ_arg;
317 
318  minX_ = min (minX_, maxX_);
319  minY_ = min (minY_, maxY_);
320  minZ_ = min (minZ_, maxZ_);
321 
322  maxX_ = max (minX_, maxX_);
323  maxY_ = max (minY_, maxY_);
324  maxZ_ = max (minZ_, maxZ_);
325 
326  // generate bit masks for octree
327  getKeyBitSize ();
328 
329  boundingBoxDefined_ = true;
330 }
331 
333 template<typename PointT, typename LeafT, typename BranchT, typename OctreeT> void
335  const double maxX_arg, const double maxY_arg, const double maxZ_arg)
336 {
337  // bounding box cannot be changed once the octree contains elements
338  assert (this->leafCount_ == 0);
339 
340  assert (maxX_arg >= 0.0f);
341  assert (maxY_arg >= 0.0f);
342  assert (maxZ_arg >= 0.0f);
343 
344  minX_ = 0.0f;
345  maxX_ = maxX_arg;
346 
347  minY_ = 0.0f;
348  maxY_ = maxY_arg;
349 
350  minZ_ = 0.0f;
351  maxZ_ = maxZ_arg;
352 
353  minX_ = min (minX_, maxX_);
354  minY_ = min (minY_, maxY_);
355  minZ_ = min (minZ_, maxZ_);
356 
357  maxX_ = max (minX_, maxX_);
358  maxY_ = max (minY_, maxY_);
359  maxZ_ = max (minZ_, maxZ_);
360 
361  // generate bit masks for octree
362  getKeyBitSize ();
363 
364  boundingBoxDefined_ = true;
365 }
366 
368 template<typename PointT, typename LeafT, typename BranchT, typename OctreeT> void
370 {
371  // bounding box cannot be changed once the octree contains elements
372  assert (this->leafCount_ == 0);
373 
374  assert (cubeLen_arg >= 0.0f);
375 
376  minX_ = 0.0f;
377  maxX_ = cubeLen_arg;
378 
379  minY_ = 0.0f;
380  maxY_ = cubeLen_arg;
381 
382  minZ_ = 0.0f;
383  maxZ_ = cubeLen_arg;
384 
385  minX_ = min (minX_, maxX_);
386  minY_ = min (minY_, maxY_);
387  minZ_ = min (minZ_, maxZ_);
388 
389  maxX_ = max (minX_, maxX_);
390  maxY_ = max (minY_, maxY_);
391  maxZ_ = max (minZ_, maxZ_);
392 
393  // generate bit masks for octree
394  getKeyBitSize ();
395 
396  boundingBoxDefined_ = true;
397 }
398 
400 template<typename PointT, typename LeafT, typename BranchT, typename OctreeT> void
402  double& minX_arg, double& minY_arg, double& minZ_arg,
403  double& maxX_arg, double& maxY_arg, double& maxZ_arg) const
404 {
405  minX_arg = minX_;
406  minY_arg = minY_;
407  minZ_arg = minZ_;
408 
409  maxX_arg = maxX_;
410  maxY_arg = maxY_;
411  maxZ_arg = maxZ_;
412 }
413 
415 template<typename PointT, typename LeafT, typename BranchT, typename OctreeT>
416 void
418 {
419 
420  const float minValue = std::numeric_limits<float>::epsilon ();
421 
422  // increase octree size until point fits into bounding box
423  while (true)
424  {
425  bool bLowerBoundViolationX = (pointIdx_arg.x < minX_);
426  bool bLowerBoundViolationY = (pointIdx_arg.y < minY_);
427  bool bLowerBoundViolationZ = (pointIdx_arg.z < minZ_);
428 
429  bool bUpperBoundViolationX = (pointIdx_arg.x >= maxX_);
430  bool bUpperBoundViolationY = (pointIdx_arg.y >= maxY_);
431  bool bUpperBoundViolationZ = (pointIdx_arg.z >= maxZ_);
432 
433  // do we violate any bounds?
434  if (bLowerBoundViolationX || bLowerBoundViolationY || bLowerBoundViolationZ || bUpperBoundViolationX
435  || bUpperBoundViolationY || bUpperBoundViolationZ )
436  {
437 
438  if (boundingBoxDefined_)
439  {
440 
441  double octreeSideLen;
442  unsigned char childIdx;
443 
444  // octree not empty - we add another tree level and thus increase its size by a factor of 2*2*2
445  childIdx = static_cast<unsigned char> (((!bUpperBoundViolationX) << 2) | ((!bUpperBoundViolationY) << 1)
446  | ((!bUpperBoundViolationZ)));
447 
448  BranchNode* newRootBranch;
449 
450  newRootBranch = this->branchNodePool_.popNode();
451  this->branchCount_++;
452 
453  this->setBranchChildPtr (*newRootBranch, childIdx, this->rootNode_);
454 
455  this->rootNode_ = newRootBranch;
456 
457  octreeSideLen = static_cast<double> (1 << this->octreeDepth_) * resolution_;
458 
459  if (!bUpperBoundViolationX)
460  minX_ -= octreeSideLen;
461 
462  if (!bUpperBoundViolationY)
463  minY_ -= octreeSideLen;
464 
465  if (!bUpperBoundViolationZ)
466  minZ_ -= octreeSideLen;
467 
468  // configure tree depth of octree
469  this->octreeDepth_++;
470  this->setTreeDepth (this->octreeDepth_);
471 
472  // recalculate bounding box width
473  octreeSideLen = static_cast<double> (1 << this->octreeDepth_) * resolution_ - minValue;
474 
475  // increase octree bounding box
476  maxX_ = minX_ + octreeSideLen;
477  maxY_ = minY_ + octreeSideLen;
478  maxZ_ = minZ_ + octreeSideLen;
479 
480  }
481  // bounding box is not defined - set it to point position
482  else
483  {
484  // octree is empty - we set the center of the bounding box to our first pixel
485  this->minX_ = pointIdx_arg.x - this->resolution_ / 2;
486  this->minY_ = pointIdx_arg.y - this->resolution_ / 2;
487  this->minZ_ = pointIdx_arg.z - this->resolution_ / 2;
488 
489  this->maxX_ = pointIdx_arg.x + this->resolution_ / 2;
490  this->maxY_ = pointIdx_arg.y + this->resolution_ / 2;
491  this->maxZ_ = pointIdx_arg.z + this->resolution_ / 2;
492 
493  getKeyBitSize ();
494 
495  boundingBoxDefined_ = true;
496  }
497 
498  }
499  else
500  // no bound violations anymore - leave while loop
501  break;
502  }
503 }
504 
506 template<typename PointT, typename LeafT, typename BranchT, typename OctreeT> void
508 {
509  OctreeKey key;
510 
511  assert (pointIdx_arg < static_cast<int> (input_->points.size ()));
512 
513  const PointT& point = input_->points[pointIdx_arg];
514 
515  // make sure bounding box is big enough
516  adoptBoundingBoxToPoint (point);
517 
518  // generate key
519  genOctreeKeyforPoint (point, key);
520 
521  // add point to octree at key
522  this->addData (key, pointIdx_arg);
523 }
524 
526 template<typename PointT, typename LeafT, typename BranchT, typename OctreeT> const PointT&
528 {
529  // retrieve point from input cloud
530  assert (index_arg < static_cast<unsigned int> (input_->points.size ()));
531  return (this->input_->points[index_arg]);
532 }
533 
535 template<typename PointT, typename LeafT, typename BranchT, typename OctreeT> LeafT*
537 {
538  OctreeKey key;
539 
540  // generate key for point
541  this->genOctreeKeyforPoint (point, key);
542 
543  return (this->findLeaf (key));
544 }
545 
547 template<typename PointT, typename LeafT, typename BranchT, typename OctreeT> void
549 {
550  unsigned int maxVoxels;
551 
552  unsigned int maxKeyX;
553  unsigned int maxKeyY;
554  unsigned int maxKeyZ;
555 
556  double octreeSideLen;
557 
558  const float minValue = std::numeric_limits<float>::epsilon();
559 
560  // find maximum key values for x, y, z
561  maxKeyX = static_cast<unsigned int> ((maxX_ - minX_) / resolution_);
562  maxKeyY = static_cast<unsigned int> ((maxY_ - minY_) / resolution_);
563  maxKeyZ = static_cast<unsigned int> ((maxZ_ - minZ_) / resolution_);
564 
565  // find maximum amount of keys
566  maxVoxels = max (max (max (maxKeyX, maxKeyY), maxKeyZ), static_cast<unsigned int> (2));
567 
568 
569  // tree depth == amount of bits of maxVoxels
570  this->octreeDepth_ = max ((min (static_cast<unsigned int> (OCT_MAXTREEDEPTH), static_cast<unsigned int> (ceil (this->Log2 (maxVoxels)-minValue)))),
571  static_cast<unsigned int> (0));
572 
573  octreeSideLen = static_cast<double> (1 << this->octreeDepth_) * resolution_-minValue;
574 
575  if (this->leafCount_ == 0)
576  {
577  double octreeOversizeX;
578  double octreeOversizeY;
579  double octreeOversizeZ;
580 
581  octreeOversizeX = (octreeSideLen - (maxX_ - minX_)) / 2.0;
582  octreeOversizeY = (octreeSideLen - (maxY_ - minY_)) / 2.0;
583  octreeOversizeZ = (octreeSideLen - (maxZ_ - minZ_)) / 2.0;
584 
585  minX_ -= octreeOversizeX;
586  minY_ -= octreeOversizeY;
587  minZ_ -= octreeOversizeZ;
588 
589  maxX_ += octreeOversizeX;
590  maxY_ += octreeOversizeY;
591  maxZ_ += octreeOversizeZ;
592  }
593  else
594  {
595  maxX_ = minX_ + octreeSideLen;
596  maxY_ = minY_ + octreeSideLen;
597  maxZ_ = minZ_ + octreeSideLen;
598  }
599 
600  // configure tree depth of octree
601  this->setTreeDepth (this->octreeDepth_);
602 
603 }
604 
606 template<typename PointT, typename LeafT, typename BranchT, typename OctreeT> void
608  OctreeKey & key_arg) const
609  {
610  // calculate integer key for point coordinates
611  key_arg.x = static_cast<unsigned int> ((point_arg.x - this->minX_) / this->resolution_);
612  key_arg.y = static_cast<unsigned int> ((point_arg.y - this->minY_) / this->resolution_);
613  key_arg.z = static_cast<unsigned int> ((point_arg.z - this->minZ_) / this->resolution_);
614  }
615 
617 template<typename PointT, typename LeafT, typename BranchT, typename OctreeT> void
619  const double pointX_arg, const double pointY_arg,
620  const double pointZ_arg, OctreeKey & key_arg) const
621 {
622  PointT tempPoint;
623 
624  tempPoint.x = static_cast<float> (pointX_arg);
625  tempPoint.y = static_cast<float> (pointY_arg);
626  tempPoint.z = static_cast<float> (pointZ_arg);
627 
628  // generate key for point
629  genOctreeKeyforPoint (tempPoint, key_arg);
630 }
631 
633 template<typename PointT, typename LeafT, typename BranchT, typename OctreeT> bool
635 {
636  const PointT tempPoint = getPointByIndex (data_arg);
637 
638  // generate key for point
639  genOctreeKeyforPoint (tempPoint, key_arg);
640 
641  return (true);
642 }
643 
645 template<typename PointT, typename LeafT, typename BranchT, typename OctreeT> void
647 {
648  // define point to leaf node voxel center
649  point.x = static_cast<float> ((static_cast<double> (key.x) + 0.5f) * this->resolution_ + this->minX_);
650  point.y = static_cast<float> ((static_cast<double> (key.y) + 0.5f) * this->resolution_ + this->minY_);
651  point.z = static_cast<float> ((static_cast<double> (key.z) + 0.5f) * this->resolution_ + this->minZ_);
652 }
653 
655 template<typename PointT, typename LeafT, typename BranchT, typename OctreeT> void
657  const OctreeKey & key_arg,
658  unsigned int treeDepth_arg,
659  PointT& point_arg) const
660 {
661  // generate point for voxel center defined by treedepth (bitLen) and key
662  point_arg.x = static_cast<float> ((static_cast <double> (key_arg.x) + 0.5f) * (this->resolution_ * static_cast<double> (1 << (this->octreeDepth_ - treeDepth_arg))) + this->minX_);
663  point_arg.y = static_cast<float> ((static_cast <double> (key_arg.y) + 0.5f) * (this->resolution_ * static_cast<double> (1 << (this->octreeDepth_ - treeDepth_arg))) + this->minY_);
664  point_arg.z = static_cast<float> ((static_cast <double> (key_arg.z) + 0.5f) * (this->resolution_ * static_cast<double> (1 << (this->octreeDepth_ - treeDepth_arg))) + this->minZ_);
665 }
666 
668 template<typename PointT, typename LeafT, typename BranchT, typename OctreeT> void
670  const OctreeKey & key_arg,
671  unsigned int treeDepth_arg,
672  Eigen::Vector3f &min_pt,
673  Eigen::Vector3f &max_pt) const
674 {
675  // calculate voxel size of current tree depth
676  double voxel_side_len = this->resolution_ * static_cast<double> (1 << (this->octreeDepth_ - treeDepth_arg));
677 
678  // calculate voxel bounds
679  min_pt (0) = static_cast<float> (static_cast<double> (key_arg.x) * voxel_side_len + this->minX_);
680  min_pt (1) = static_cast<float> (static_cast<double> (key_arg.y) * voxel_side_len + this->minY_);
681  min_pt (2) = static_cast<float> (static_cast<double> (key_arg.z) * voxel_side_len + this->minZ_);
682 
683  max_pt (0) = static_cast<float> (static_cast<double> (key_arg.x + 1) * voxel_side_len + this->minX_);
684  max_pt (1) = static_cast<float> (static_cast<double> (key_arg.y + 1) * voxel_side_len + this->minY_);
685  max_pt (2) = static_cast<float> (static_cast<double> (key_arg.z + 1) * voxel_side_len + this->minZ_);
686 }
687 
689 template<typename PointT, typename LeafT, typename BranchT, typename OctreeT> double
691 {
692  double sideLen;
693 
694  // side length of the voxel cube increases exponentially with the octree depth
695  sideLen = this->resolution_ * static_cast<double>(1 << (this->octreeDepth_ - treeDepth_arg));
696 
697  // squared voxel side length
698  sideLen *= sideLen;
699 
700  return (sideLen);
701 }
702 
704 template<typename PointT, typename LeafT, typename BranchT, typename OctreeT> double
706 {
707  // return the squared side length of the voxel cube as a function of the octree depth
708  return (getVoxelSquaredSideLen (treeDepth_arg) * 3);
709 }
710 
712 template<typename PointT, typename LeafT, typename BranchT, typename OctreeT> int
714  const BranchNode* node_arg,
715  const OctreeKey& key_arg,
716  AlignedPointTVector &voxelCenterList_arg) const
717 {
718  // child iterator
719  unsigned char childIdx;
720 
721  int voxelCount = 0;
722 
723  // iterate over all children
724  for (childIdx = 0; childIdx < 8; childIdx++)
725  {
726  if (!this->branchHasChild (*node_arg, childIdx))
727  continue;
728 
729  const OctreeNode * childNode;
730  childNode = this->getBranchChildPtr (*node_arg, childIdx);
731 
732  // generate new key for current branch voxel
733  OctreeKey newKey;
734  newKey.x = (key_arg.x << 1) | (!!(childIdx & (1 << 2)));
735  newKey.y = (key_arg.y << 1) | (!!(childIdx & (1 << 1)));
736  newKey.z = (key_arg.z << 1) | (!!(childIdx & (1 << 0)));
737 
738  switch (childNode->getNodeType ())
739  {
740  case BRANCH_NODE:
741  {
742  // recursively proceed with indexed child branch
743  voxelCount += getOccupiedVoxelCentersRecursive (static_cast<const BranchNode*> (childNode), newKey, voxelCenterList_arg);
744  break;
745  }
746  case LEAF_NODE:
747  {
748  PointT newPoint;
749 
750  genLeafNodeCenterFromOctreeKey (newKey, newPoint);
751  voxelCenterList_arg.push_back (newPoint);
752 
753  voxelCount++;
754  break;
755  }
756  default:
757  break;
758  }
759  }
760  return (voxelCount);
761 }
762 
763 #define PCL_INSTANTIATE_OctreePointCloudSingleBufferWithLeafDataTVector(T) template class PCL_EXPORTS pcl::octree::OctreePointCloud<T, pcl::octree::OctreeContainerDataTVector<int> , pcl::octree::OctreeContainerEmpty<int>, pcl::octree::OctreeBase<int, pcl::octree::OctreeContainerDataTVector<int>, pcl::octree::OctreeContainerEmpty<int> > >;
764 #define PCL_INSTANTIATE_OctreePointCloudDoubleBufferWithLeafDataTVector(T) template class PCL_EXPORTS pcl::octree::OctreePointCloud<T, pcl::octree::OctreeContainerDataTVector<int> , pcl::octree::OctreeContainerEmpty<int>, pcl::octree::Octree2BufBase<int, pcl::octree::OctreeContainerDataTVector<int>, pcl::octree::OctreeContainerEmpty<int> > >;
765 
766 #define PCL_INSTANTIATE_OctreePointCloudSingleBufferWithLeafDataT(T) template class PCL_EXPORTS pcl::octree::OctreePointCloud<T, pcl::octree::OctreeLeafDataT<int>, pcl::octree::OctreeContainerEmpty<int> , pcl::octree::OctreeBase<int, pcl::octree::OctreeContainerDataT<int>, pcl::octree::OctreeContainerEmpty<int> > >;
767 #define PCL_INSTANTIATE_OctreePointCloudDoubleBufferWithLeafDataT(T) template class PCL_EXPORTS pcl::octree::OctreePointCloud<T, pcl::octree::OctreeLeafDataT<int>, pcl::octree::OctreeContainerEmpty<int> , pcl::octree::Octree2BufBase<int, pcl::octree::OctreeContainerDataT<int>, pcl::octree::OctreeContainerEmpty<int> > >;
768 
769 #define PCL_INSTANTIATE_OctreePointCloudSingleBufferWithEmptyLeaf(T) template class PCL_EXPORTS pcl::octree::OctreePointCloud<T, pcl::octree::OctreeLeafEmpty<int>, pcl::octree::OctreeContainerEmpty<int> , pcl::octree::OctreeBase<int, pcl::octree::OctreeContainerDataT<int>, pcl::octree::OctreeContainerEmpty<int> > >;
770 #define PCL_INSTANTIATE_OctreePointCloudDoubleBufferWithEmptyLeaf(T) template class PCL_EXPORTS pcl::octree::OctreePointCloud<T, pcl::octree::OctreeLeafEmpty<int>, pcl::octree::OctreeContainerEmpty<int> , pcl::octree::Octree2BufBase<int, pcl::octree::OctreeContainerDataT<int>, pcl::octree::OctreeContainerEmpty<int> > >;
771 
772 #endif /* OCTREE_POINTCLOUD_HPP_ */