Point Cloud Library (PCL)  1.6.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
octree_search.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-2011, 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_search.hpp 6119 2012-07-03 18:50:04Z aichim $
37  */
38 
39 #ifndef PCL_OCTREE_SEARCH_IMPL_H_
40 #define PCL_OCTREE_SEARCH_IMPL_H_
41 
42 #include <pcl/point_cloud.h>
43 #include <pcl/point_types.h>
44 
45 #include <pcl/common/common.h>
46 #include <assert.h>
47 
49 template<typename PointT, typename LeafT, typename BranchT> bool
51  std::vector<int>& pointIdx_data)
52 {
53  assert (isFinite (point) && "Invalid (NaN, Inf) point coordinates given to nearestKSearch!");
54  OctreeKey key;
55  bool b_success = false;
56 
57  // generate key
58  this->genOctreeKeyforPoint (point, key);
59 
60  LeafT* leaf = this->findLeaf (key);
61 
62  if (leaf)
63  {
64  leaf->getData (pointIdx_data);
65  b_success = true;
66  }
67 
68  return (b_success);
69 }
70 
72 template<typename PointT, typename LeafT, typename BranchT> bool
74  std::vector<int>& pointIdx_data)
75 {
76  const PointT search_point = this->getPointByIndex (index);
77  return (this->voxelSearch (search_point, pointIdx_data));
78 }
79 
81 template<typename PointT, typename LeafT, typename BranchT> int
83  std::vector<int> &k_indices,
84  std::vector<float> &k_sqr_distances)
85 {
86  assert(this->leafCount_>0);
87  assert (isFinite (p_q) && "Invalid (NaN, Inf) point coordinates given to nearestKSearch!");
88 
89  k_indices.clear ();
90  k_sqr_distances.clear ();
91 
92  if (k < 1)
93  return 0;
94 
95  unsigned int i;
96  unsigned int resultCount;
97 
98  prioPointQueueEntry pointEntry;
99  std::vector<prioPointQueueEntry> pointCandidates;
100 
101  OctreeKey key;
102  key.x = key.y = key.z = 0;
103 
104  // initalize smallest point distance in search with high value
105  double smallestDist = numeric_limits<double>::max ();
106 
107  getKNearestNeighborRecursive (p_q, k, this->rootNode_, key, 1, smallestDist, pointCandidates);
108 
109  resultCount = static_cast<unsigned int> (pointCandidates.size ());
110 
111  k_indices.resize (resultCount);
112  k_sqr_distances.resize (resultCount);
113 
114  for (i = 0; i < resultCount; ++i)
115  {
116  k_indices [i] = pointCandidates [i].pointIdx_;
117  k_sqr_distances [i] = pointCandidates [i].pointDistance_;
118  }
119 
120  return static_cast<int> (k_indices.size ());
121 }
122 
124 template<typename PointT, typename LeafT, typename BranchT> int
126  std::vector<int> &k_indices,
127  std::vector<float> &k_sqr_distances)
128 {
129  const PointT search_point = this->getPointByIndex (index);
130  return (nearestKSearch (search_point, k, k_indices, k_sqr_distances));
131 }
132 
134 template<typename PointT, typename LeafT, typename BranchT> void
136  int &result_index,
137  float &sqr_distance)
138 {
139  assert(this->leafCount_>0);
140  assert (isFinite (p_q) && "Invalid (NaN, Inf) point coordinates given to nearestKSearch!");
141 
142  OctreeKey key;
143  key.x = key.y = key.z = 0;
144 
145  approxNearestSearchRecursive (p_q, this->rootNode_, key, 1, result_index, sqr_distance);
146 
147  return;
148 }
149 
151 template<typename PointT, typename LeafT, typename BranchT> void
153  float &sqr_distance)
154 {
155  const PointT searchPoint = this->getPointByIndex (query_index);
156 
157  return (approxNearestSearch (searchPoint, result_index, sqr_distance));
158 }
159 
161 template<typename PointT, typename LeafT, typename BranchT> int
163  std::vector<int> &k_indices,
164  std::vector<float> &k_sqr_distances,
165  unsigned int max_nn) const
166 {
167  assert (isFinite (p_q) && "Invalid (NaN, Inf) point coordinates given to nearestKSearch!");
168  OctreeKey key;
169  key.x = key.y = key.z = 0;
170 
171  k_indices.clear ();
172  k_sqr_distances.clear ();
173 
174  getNeighborsWithinRadiusRecursive (p_q, radius * radius, this->rootNode_, key, 1, k_indices, k_sqr_distances,
175  max_nn);
176 
177  return (static_cast<int> (k_indices.size ()));
178 }
179 
181 template<typename PointT, typename LeafT, typename BranchT> int
183  std::vector<int> &k_indices,
184  std::vector<float> &k_sqr_distances,
185  unsigned int max_nn) const
186 {
187  const PointT search_point = this->getPointByIndex (index);
188 
189  return (radiusSearch (search_point, radius, k_indices, k_sqr_distances, max_nn));
190 }
191 
193 template<typename PointT, typename LeafT, typename BranchT> int
195  const Eigen::Vector3f &max_pt,
196  std::vector<int> &k_indices) const
197 {
198 
199  OctreeKey key;
200  key.x = key.y = key.z = 0;
201 
202  k_indices.clear ();
203 
204  boxSearchRecursive (min_pt, max_pt, this->rootNode_, key, 1, k_indices);
205 
206  return (static_cast<int> (k_indices.size ()));
207 
208 }
209 
211 template<typename PointT, typename LeafT, typename BranchT> double
213  const PointT & point, unsigned int K, const BranchNode* node, const OctreeKey& key, unsigned int treeDepth,
214  const double squaredSearchRadius, std::vector<prioPointQueueEntry>& pointCandidates) const
215 {
216  std::vector<prioBranchQueueEntry> searchEntryHeap;
217  searchEntryHeap.resize (8);
218 
219  unsigned char childIdx;
220 
221  OctreeKey newKey;
222 
223  double smallestSquaredDist = squaredSearchRadius;
224 
225  // get spatial voxel information
226  double voxelSquaredDiameter = this->getVoxelSquaredDiameter (treeDepth);
227 
228  // iterate over all children
229  for (childIdx = 0; childIdx < 8; childIdx++)
230  {
231  if (this->branchHasChild (*node, childIdx))
232  {
233  PointT voxelCenter;
234 
235  searchEntryHeap[childIdx].key.x = (key.x << 1) + (!!(childIdx & (1 << 2)));
236  searchEntryHeap[childIdx].key.y = (key.y << 1) + (!!(childIdx & (1 << 1)));
237  searchEntryHeap[childIdx].key.z = (key.z << 1) + (!!(childIdx & (1 << 0)));
238 
239  // generate voxel center point for voxel at key
240  this->genVoxelCenterFromOctreeKey (searchEntryHeap[childIdx].key, treeDepth, voxelCenter);
241 
242  // generate new priority queue element
243  searchEntryHeap[childIdx].node = this->getBranchChildPtr (*node, childIdx);
244  searchEntryHeap[childIdx].pointDistance = pointSquaredDist (voxelCenter, point);
245  }
246  else
247  {
248  searchEntryHeap[childIdx].pointDistance = numeric_limits<float>::infinity ();
249  }
250  }
251 
252  std::sort (searchEntryHeap.begin (), searchEntryHeap.end ());
253 
254  // iterate over all children in priority queue
255  // check if the distance to search candidate is smaller than the best point distance (smallestSquaredDist)
256  while ((!searchEntryHeap.empty ())
257  && (searchEntryHeap.back ().pointDistance
258  < smallestSquaredDist + voxelSquaredDiameter / 4.0 + sqrt (smallestSquaredDist * voxelSquaredDiameter)
259  - this->epsilon_))
260  {
261  const OctreeNode* childNode;
262 
263  // read from priority queue element
264  childNode = searchEntryHeap.back ().node;
265  newKey = searchEntryHeap.back ().key;
266 
267  if (treeDepth < this->octreeDepth_)
268  {
269  // we have not reached maximum tree depth
270  smallestSquaredDist = getKNearestNeighborRecursive (point, K, static_cast<const BranchNode*> (childNode), newKey, treeDepth + 1,
271  smallestSquaredDist, pointCandidates);
272  }
273  else
274  {
275  // we reached leaf node level
276 
277  float squaredDist;
278  size_t i;
279  vector<int> decodedPointVector;
280 
281  const LeafNode* childLeaf = static_cast<const LeafNode*> (childNode);
282 
283  // decode leaf node into decodedPointVector
284  childLeaf->getData (decodedPointVector);
285 
286  // Linearly iterate over all decoded (unsorted) points
287  for (i = 0; i < decodedPointVector.size (); i++)
288  {
289 
290  const PointT& candidatePoint = this->getPointByIndex (decodedPointVector[i]);
291 
292  // calculate point distance to search point
293  squaredDist = pointSquaredDist (candidatePoint, point);
294 
295  // check if a closer match is found
296  if (squaredDist < smallestSquaredDist)
297  {
298  prioPointQueueEntry pointEntry;
299 
300  pointEntry.pointDistance_ = squaredDist;
301  pointEntry.pointIdx_ = decodedPointVector[i];
302  pointCandidates.push_back (pointEntry);
303  }
304  }
305 
306  std::sort (pointCandidates.begin (), pointCandidates.end ());
307 
308  if (pointCandidates.size () > K)
309  pointCandidates.resize (K);
310 
311  if (pointCandidates.size () == K)
312  smallestSquaredDist = pointCandidates.back ().pointDistance_;
313  }
314  // pop element from priority queue
315  searchEntryHeap.pop_back ();
316  }
317 
318  return (smallestSquaredDist);
319 }
320 
322 template<typename PointT, typename LeafT, typename BranchT> void
324  const PointT & point, const double radiusSquared, const BranchNode* node, const OctreeKey& key,
325  unsigned int treeDepth, std::vector<int>& k_indices, std::vector<float>& k_sqr_distances,
326  unsigned int max_nn) const
327 {
328  // child iterator
329  unsigned char childIdx;
330 
331  // get spatial voxel information
332  double voxelSquaredDiameter = this->getVoxelSquaredDiameter (treeDepth);
333 
334  // iterate over all children
335  for (childIdx = 0; childIdx < 8; childIdx++)
336  {
337  if (!this->branchHasChild (*node, childIdx))
338  continue;
339 
340  const OctreeNode* childNode;
341  childNode = this->getBranchChildPtr (*node, childIdx);
342 
343  OctreeKey newKey;
344  PointT voxelCenter;
345  float squaredDist;
346 
347  // generate new key for current branch voxel
348  newKey.x = (key.x << 1) + (!!(childIdx & (1 << 2)));
349  newKey.y = (key.y << 1) + (!!(childIdx & (1 << 1)));
350  newKey.z = (key.z << 1) + (!!(childIdx & (1 << 0)));
351 
352  // generate voxel center point for voxel at key
353  this->genVoxelCenterFromOctreeKey (newKey, treeDepth, voxelCenter);
354 
355  // calculate distance to search point
356  squaredDist = pointSquaredDist (static_cast<const PointT&> (voxelCenter), point);
357 
358  // if distance is smaller than search radius
359  if (squaredDist + this->epsilon_
360  <= voxelSquaredDiameter / 4.0 + radiusSquared + sqrt (voxelSquaredDiameter * radiusSquared))
361  {
362 
363  if (treeDepth < this->octreeDepth_)
364  {
365  // we have not reached maximum tree depth
366  getNeighborsWithinRadiusRecursive (point, radiusSquared, static_cast<const BranchNode*> (childNode), newKey, treeDepth + 1,
367  k_indices, k_sqr_distances, max_nn);
368  if (max_nn != 0 && k_indices.size () == static_cast<unsigned int> (max_nn))
369  return;
370  }
371  else
372  {
373  // we reached leaf node level
374 
375  size_t i;
376  const LeafNode* childLeaf = static_cast<const LeafNode*> (childNode);
377  vector<int> decodedPointVector;
378 
379  // decode leaf node into decodedPointVector
380  childLeaf->getData (decodedPointVector);
381 
382  // Linearly iterate over all decoded (unsorted) points
383  for (i = 0; i < decodedPointVector.size (); i++)
384  {
385  const PointT& candidatePoint = this->getPointByIndex (decodedPointVector[i]);
386 
387  // calculate point distance to search point
388  squaredDist = pointSquaredDist (candidatePoint, point);
389 
390  // check if a match is found
391  if (squaredDist > radiusSquared)
392  continue;
393 
394  // add point to result vector
395  k_indices.push_back (decodedPointVector[i]);
396  k_sqr_distances.push_back (squaredDist);
397 
398  if (max_nn != 0 && k_indices.size () == static_cast<unsigned int> (max_nn))
399  return;
400  }
401  }
402  }
403  }
404 }
405 
407 template<typename PointT, typename LeafT, typename BranchT> void
409  const BranchNode* node,
410  const OctreeKey& key,
411  unsigned int treeDepth,
412  int& result_index,
413  float& sqr_distance)
414 {
415  unsigned char childIdx;
416  unsigned char minChildIdx;
417  double minVoxelCenterDistance;
418 
419  OctreeKey minChildKey;
420  OctreeKey newKey;
421 
422  const OctreeNode* childNode;
423 
424  // set minimum voxel distance to maximum value
425  minVoxelCenterDistance = numeric_limits<double>::max ();
426 
427  minChildIdx = 0xFF;
428 
429  // iterate over all children
430  for (childIdx = 0; childIdx < 8; childIdx++)
431  {
432  if (!this->branchHasChild (*node, childIdx))
433  continue;
434 
435  PointT voxelCenter;
436  double voxelPointDist;
437 
438  newKey.x = (key.x << 1) + (!!(childIdx & (1 << 2)));
439  newKey.y = (key.y << 1) + (!!(childIdx & (1 << 1)));
440  newKey.z = (key.z << 1) + (!!(childIdx & (1 << 0)));
441 
442  // generate voxel center point for voxel at key
443  this->genVoxelCenterFromOctreeKey (newKey, treeDepth, voxelCenter);
444 
445  voxelPointDist = pointSquaredDist (voxelCenter, point);
446 
447  // search for child voxel with shortest distance to search point
448  if (voxelPointDist >= minVoxelCenterDistance)
449  continue;
450 
451  minVoxelCenterDistance = voxelPointDist;
452  minChildIdx = childIdx;
453  minChildKey = newKey;
454  }
455 
456  // make sure we found at least one branch child
457  assert(minChildIdx<8);
458 
459  childNode = this->getBranchChildPtr (*node, minChildIdx);
460 
461  if (treeDepth < this->octreeDepth_)
462  {
463  // we have not reached maximum tree depth
464  approxNearestSearchRecursive (point, static_cast<const BranchNode*> (childNode), minChildKey, treeDepth + 1, result_index,
465  sqr_distance);
466  }
467  else
468  {
469  // we reached leaf node level
470 
471  double squaredDist;
472  double smallestSquaredDist;
473  size_t i;
474  vector<int> decodedPointVector;
475 
476  const LeafNode* childLeaf = static_cast<const LeafNode*> (childNode);
477 
478  smallestSquaredDist = numeric_limits<double>::max ();
479 
480  // decode leaf node into decodedPointVector
481  childLeaf->getData (decodedPointVector);
482 
483  // Linearly iterate over all decoded (unsorted) points
484  for (i = 0; i < decodedPointVector.size (); i++)
485  {
486  const PointT& candidatePoint = this->getPointByIndex (decodedPointVector[i]);
487 
488  // calculate point distance to search point
489  squaredDist = pointSquaredDist (candidatePoint, point);
490 
491  // check if a closer match is found
492  if (squaredDist >= smallestSquaredDist)
493  continue;
494 
495  result_index = decodedPointVector[i];
496  smallestSquaredDist = squaredDist;
497  sqr_distance = static_cast<float> (squaredDist);
498  }
499  }
500 }
501 
503 template<typename PointT, typename LeafT, typename BranchT> float
505  const PointT & pointB) const
506 {
507  return (pointA.getVector3fMap () - pointB.getVector3fMap ()).squaredNorm ();
508 }
509 
511 template<typename PointT, typename LeafT, typename BranchT> void
513  const Eigen::Vector3f &max_pt,
514  const BranchNode* node,
515  const OctreeKey& key,
516  unsigned int treeDepth,
517  std::vector<int>& k_indices) const
518 {
519  // child iterator
520  unsigned char childIdx;
521 
522  // iterate over all children
523  for (childIdx = 0; childIdx < 8; childIdx++)
524  {
525 
526  const OctreeNode* childNode;
527  childNode = this->getBranchChildPtr (*node, childIdx);
528 
529  if (!childNode)
530  continue;
531 
532  OctreeKey newKey;
533  // generate new key for current branch voxel
534  newKey.x = (key.x << 1) + (!!(childIdx & (1 << 2)));
535  newKey.y = (key.y << 1) + (!!(childIdx & (1 << 1)));
536  newKey.z = (key.z << 1) + (!!(childIdx & (1 << 0)));
537 
538  // voxel corners
539  Eigen::Vector3f lowerVoxelCorner;
540  Eigen::Vector3f upperVoxelCorner;
541  // get voxel coordinates
542  this->genVoxelBoundsFromOctreeKey (newKey, treeDepth, lowerVoxelCorner, upperVoxelCorner);
543 
544  // test if search region overlap with voxel space
545 
546  if ( !( (lowerVoxelCorner (0) > max_pt (0)) || (min_pt (0) > upperVoxelCorner(0)) ||
547  (lowerVoxelCorner (1) > max_pt (1)) || (min_pt (1) > upperVoxelCorner(1)) ||
548  (lowerVoxelCorner (2) > max_pt (2)) || (min_pt (2) > upperVoxelCorner(2)) ) )
549  {
550 
551  if (treeDepth < this->octreeDepth_)
552  {
553  // we have not reached maximum tree depth
554  boxSearchRecursive (min_pt, max_pt, static_cast<const BranchNode*> (childNode), newKey, treeDepth + 1, k_indices);
555  }
556  else
557  {
558  // we reached leaf node level
559  size_t i;
560  vector<int> decodedPointVector;
561  bool bInBox;
562 
563  const LeafNode* childLeaf = static_cast<const LeafNode*> (childNode);
564 
565  // decode leaf node into decodedPointVector
566  childLeaf->getData (decodedPointVector);
567 
568  // Linearly iterate over all decoded (unsorted) points
569  for (i = 0; i < decodedPointVector.size (); i++)
570  {
571  const PointT& candidatePoint = this->getPointByIndex (decodedPointVector[i]);
572 
573  // check if point falls within search box
574  bInBox = ( (candidatePoint.x > min_pt (0)) && (candidatePoint.x < max_pt (0)) &&
575  (candidatePoint.y > min_pt (1)) && (candidatePoint.y < max_pt (1)) &&
576  (candidatePoint.z > min_pt (2)) && (candidatePoint.z < max_pt (2)) );
577 
578  if (bInBox)
579  // add to result vector
580  k_indices.push_back (decodedPointVector[i]);
581  }
582  }
583  }
584  }
585 }
586 
588 template<typename PointT, typename LeafT, typename BranchT> int
590  Eigen::Vector3f origin, Eigen::Vector3f direction, AlignedPointTVector &voxelCenterList,
591  int maxVoxelCount) const
592 {
593  OctreeKey key;
594  key.x = key.y = key.z = 0;
595 
596  voxelCenterList.clear ();
597 
598  // Voxel childIdx remapping
599  unsigned char a = 0;
600 
601  double minX, minY, minZ, maxX, maxY, maxZ;
602 
603  initIntersectedVoxel (origin, direction, minX, minY, minZ, maxX, maxY, maxZ, a);
604 
605  if (max (max (minX, minY), minZ) < min (min (maxX, maxY), maxZ))
606  return getIntersectedVoxelCentersRecursive (minX, minY, minZ, maxX, maxY, maxZ, a, this->rootNode_, key,
607  voxelCenterList, maxVoxelCount);
608 
609  return (0);
610 }
611 
613 template<typename PointT, typename LeafT, typename BranchT> int
615  Eigen::Vector3f origin, Eigen::Vector3f direction, std::vector<int> &k_indices,
616  int maxVoxelCount) const
617 {
618  OctreeKey key;
619  key.x = key.y = key.z = 0;
620 
621  k_indices.clear ();
622 
623  // Voxel childIdx remapping
624  unsigned char a = 0;
625  double minX, minY, minZ, maxX, maxY, maxZ;
626 
627  initIntersectedVoxel (origin, direction, minX, minY, minZ, maxX, maxY, maxZ, a);
628 
629  if (max (max (minX, minY), minZ) < min (min (maxX, maxY), maxZ))
630  return getIntersectedVoxelIndicesRecursive (minX, minY, minZ, maxX, maxY, maxZ, a, this->rootNode_, key,
631  k_indices, maxVoxelCount);
632  return (0);
633 }
634 
636 template<typename PointT, typename LeafT, typename BranchT> int
638  double minX, double minY, double minZ, double maxX, double maxY, double maxZ, unsigned char a,
639  const OctreeNode* node, const OctreeKey& key, AlignedPointTVector &voxelCenterList, int maxVoxelCount) const
640 {
641  if (maxX < 0.0 || maxY < 0.0 || maxZ < 0.0)
642  return (0);
643 
644  // If leaf node, get voxel center and increment intersection count
645  if (node->getNodeType () == LEAF_NODE)
646  {
647  PointT newPoint;
648 
649  this->genLeafNodeCenterFromOctreeKey (key, newPoint);
650 
651  voxelCenterList.push_back (newPoint);
652 
653  return (1);
654  }
655 
656  // Voxel intersection count for branches children
657  int voxelCount = 0;
658 
659  // Voxel mid lines
660  double midX = 0.5 * (minX + maxX);
661  double midY = 0.5 * (minY + maxY);
662  double midZ = 0.5 * (minZ + maxZ);
663 
664  // First voxel node ray will intersect
665  int currNode = getFirstIntersectedNode (minX, minY, minZ, midX, midY, midZ);
666 
667  // Child index, node and key
668  unsigned char childIdx;
669  const OctreeNode *childNode;
670  OctreeKey childKey;
671 
672  do
673  {
674  if (currNode != 0)
675  childIdx = static_cast<unsigned char> (currNode ^ a);
676  else
677  childIdx = a;
678 
679  // childNode == 0 if childNode doesn't exist
680  childNode = this->getBranchChildPtr (static_cast<const BranchNode&> (*node), childIdx);
681 
682  // Generate new key for current branch voxel
683  childKey.x = (key.x << 1) | (!!(childIdx & (1 << 2)));
684  childKey.y = (key.y << 1) | (!!(childIdx & (1 << 1)));
685  childKey.z = (key.z << 1) | (!!(childIdx & (1 << 0)));
686 
687  // Recursively call each intersected child node, selecting the next
688  // node intersected by the ray. Children that do not intersect will
689  // not be traversed.
690 
691  switch (currNode)
692  {
693  case 0:
694  if (childNode)
695  voxelCount += getIntersectedVoxelCentersRecursive (minX, minY, minZ, midX, midY, midZ, a, childNode,
696  childKey, voxelCenterList, maxVoxelCount);
697  currNode = getNextIntersectedNode (midX, midY, midZ, 4, 2, 1);
698  break;
699 
700  case 1:
701  if (childNode)
702  voxelCount += getIntersectedVoxelCentersRecursive (minX, minY, midZ, midX, midY, maxZ, a, childNode,
703  childKey, voxelCenterList, maxVoxelCount);
704  currNode = getNextIntersectedNode (midX, midY, maxZ, 5, 3, 8);
705  break;
706 
707  case 2:
708  if (childNode)
709  voxelCount += getIntersectedVoxelCentersRecursive (minX, midY, minZ, midX, maxY, midZ, a, childNode,
710  childKey, voxelCenterList, maxVoxelCount);
711  currNode = getNextIntersectedNode (midX, maxY, midZ, 6, 8, 3);
712  break;
713 
714  case 3:
715  if (childNode)
716  voxelCount += getIntersectedVoxelCentersRecursive (minX, midY, midZ, midX, maxY, maxZ, a, childNode,
717  childKey, voxelCenterList, maxVoxelCount);
718  currNode = getNextIntersectedNode (midX, maxY, maxZ, 7, 8, 8);
719  break;
720 
721  case 4:
722  if (childNode)
723  voxelCount += getIntersectedVoxelCentersRecursive (midX, minY, minZ, maxX, midY, midZ, a, childNode,
724  childKey, voxelCenterList, maxVoxelCount);
725  currNode = getNextIntersectedNode (maxX, midY, midZ, 8, 6, 5);
726  break;
727 
728  case 5:
729  if (childNode)
730  voxelCount += getIntersectedVoxelCentersRecursive (midX, minY, midZ, maxX, midY, maxZ, a, childNode,
731  childKey, voxelCenterList, maxVoxelCount);
732  currNode = getNextIntersectedNode (maxX, midY, maxZ, 8, 7, 8);
733  break;
734 
735  case 6:
736  if (childNode)
737  voxelCount += getIntersectedVoxelCentersRecursive (midX, midY, minZ, maxX, maxY, midZ, a, childNode,
738  childKey, voxelCenterList, maxVoxelCount);
739  currNode = getNextIntersectedNode (maxX, maxY, midZ, 8, 8, 7);
740  break;
741 
742  case 7:
743  if (childNode)
744  voxelCount += getIntersectedVoxelCentersRecursive (midX, midY, midZ, maxX, maxY, maxZ, a, childNode,
745  childKey, voxelCenterList, maxVoxelCount);
746  currNode = 8;
747  break;
748  }
749  } while ((currNode < 8) && (maxVoxelCount <= 0 || voxelCount < maxVoxelCount));
750  return (voxelCount);
751 }
752 
754 template<typename PointT, typename LeafT, typename BranchT> int
756  double minX, double minY, double minZ, double maxX, double maxY, double maxZ, unsigned char a,
757  const OctreeNode* node, const OctreeKey& key, std::vector<int> &k_indices, int maxVoxelCount) const
758 {
759  if (maxX < 0.0 || maxY < 0.0 || maxZ < 0.0)
760  return (0);
761 
762  // If leaf node, get voxel center and increment intersection count
763  if (node->getNodeType () == LEAF_NODE)
764  {
765  const LeafNode* leaf = static_cast<const LeafNode*> (node);
766 
767  // decode leaf node into k_indices
768  leaf->getData (k_indices);
769 
770  return (1);
771  }
772 
773  // Voxel intersection count for branches children
774  int voxelCount = 0;
775 
776  // Voxel mid lines
777  double midX = 0.5 * (minX + maxX);
778  double midY = 0.5 * (minY + maxY);
779  double midZ = 0.5 * (minZ + maxZ);
780 
781  // First voxel node ray will intersect
782  int currNode = getFirstIntersectedNode (minX, minY, minZ, midX, midY, midZ);
783 
784  // Child index, node and key
785  unsigned char childIdx;
786  const OctreeNode *childNode;
787  OctreeKey childKey;
788  do
789  {
790  if (currNode != 0)
791  childIdx = static_cast<unsigned char> (currNode ^ a);
792  else
793  childIdx = a;
794 
795  // childNode == 0 if childNode doesn't exist
796  childNode = this->getBranchChildPtr (static_cast<const BranchNode&> (*node), childIdx);
797  // Generate new key for current branch voxel
798  childKey.x = (key.x << 1) | (!!(childIdx & (1 << 2)));
799  childKey.y = (key.y << 1) | (!!(childIdx & (1 << 1)));
800  childKey.z = (key.z << 1) | (!!(childIdx & (1 << 0)));
801 
802  // Recursively call each intersected child node, selecting the next
803  // node intersected by the ray. Children that do not intersect will
804  // not be traversed.
805  switch (currNode)
806  {
807  case 0:
808  if (childNode)
809  voxelCount += getIntersectedVoxelIndicesRecursive (minX, minY, minZ, midX, midY, midZ, a, childNode,
810  childKey, k_indices, maxVoxelCount);
811  currNode = getNextIntersectedNode (midX, midY, midZ, 4, 2, 1);
812  break;
813 
814  case 1:
815  if (childNode)
816  voxelCount += getIntersectedVoxelIndicesRecursive (minX, minY, midZ, midX, midY, maxZ, a, childNode,
817  childKey, k_indices, maxVoxelCount);
818  currNode = getNextIntersectedNode (midX, midY, maxZ, 5, 3, 8);
819  break;
820 
821  case 2:
822  if (childNode)
823  voxelCount += getIntersectedVoxelIndicesRecursive (minX, midY, minZ, midX, maxY, midZ, a, childNode,
824  childKey, k_indices, maxVoxelCount);
825  currNode = getNextIntersectedNode (midX, maxY, midZ, 6, 8, 3);
826  break;
827 
828  case 3:
829  if (childNode)
830  voxelCount += getIntersectedVoxelIndicesRecursive (minX, midY, midZ, midX, maxY, maxZ, a, childNode,
831  childKey, k_indices, maxVoxelCount);
832  currNode = getNextIntersectedNode (midX, maxY, maxZ, 7, 8, 8);
833  break;
834 
835  case 4:
836  if (childNode)
837  voxelCount += getIntersectedVoxelIndicesRecursive (midX, minY, minZ, maxX, midY, midZ, a, childNode,
838  childKey, k_indices, maxVoxelCount);
839  currNode = getNextIntersectedNode (maxX, midY, midZ, 8, 6, 5);
840  break;
841 
842  case 5:
843  if (childNode)
844  voxelCount += getIntersectedVoxelIndicesRecursive (midX, minY, midZ, maxX, midY, maxZ, a, childNode,
845  childKey, k_indices, maxVoxelCount);
846  currNode = getNextIntersectedNode (maxX, midY, maxZ, 8, 7, 8);
847  break;
848 
849  case 6:
850  if (childNode)
851  voxelCount += getIntersectedVoxelIndicesRecursive (midX, midY, minZ, maxX, maxY, midZ, a, childNode,
852  childKey, k_indices, maxVoxelCount);
853  currNode = getNextIntersectedNode (maxX, maxY, midZ, 8, 8, 7);
854  break;
855 
856  case 7:
857  if (childNode)
858  voxelCount += getIntersectedVoxelIndicesRecursive (midX, midY, midZ, maxX, maxY, maxZ, a, childNode,
859  childKey, k_indices, maxVoxelCount);
860  currNode = 8;
861  break;
862  }
863  } while ((currNode < 8) && (maxVoxelCount <= 0 || voxelCount < maxVoxelCount));
864 
865  return (voxelCount);
866 }
867 
868 #endif // PCL_OCTREE_SEARCH_IMPL_H_