39 #ifndef PCL_OCTREE_SEARCH_IMPL_H_
40 #define PCL_OCTREE_SEARCH_IMPL_H_
49 template<
typename Po
intT,
typename LeafT,
typename BranchT>
bool
51 std::vector<int>& pointIdx_data)
53 assert (
isFinite (point) &&
"Invalid (NaN, Inf) point coordinates given to nearestKSearch!");
55 bool b_success =
false;
58 this->genOctreeKeyforPoint (point, key);
60 LeafT* leaf = this->findLeaf (key);
64 leaf->getData (pointIdx_data);
72 template<
typename Po
intT,
typename LeafT,
typename BranchT>
bool
74 std::vector<int>& pointIdx_data)
76 const PointT search_point = this->getPointByIndex (index);
77 return (this->voxelSearch (search_point, pointIdx_data));
81 template<
typename Po
intT,
typename LeafT,
typename BranchT>
int
83 std::vector<int> &k_indices,
84 std::vector<float> &k_sqr_distances)
86 assert(this->leafCount_>0);
87 assert (
isFinite (p_q) &&
"Invalid (NaN, Inf) point coordinates given to nearestKSearch!");
90 k_sqr_distances.clear ();
96 unsigned int resultCount;
98 prioPointQueueEntry pointEntry;
99 std::vector<prioPointQueueEntry> pointCandidates;
102 key.
x = key.
y = key.
z = 0;
105 double smallestDist = numeric_limits<double>::max ();
107 getKNearestNeighborRecursive (p_q, k, this->rootNode_, key, 1, smallestDist, pointCandidates);
109 resultCount =
static_cast<unsigned int> (pointCandidates.size ());
111 k_indices.resize (resultCount);
112 k_sqr_distances.resize (resultCount);
114 for (i = 0; i < resultCount; ++i)
116 k_indices [i] = pointCandidates [i].pointIdx_;
117 k_sqr_distances [i] = pointCandidates [i].pointDistance_;
120 return static_cast<int> (k_indices.size ());
124 template<
typename Po
intT,
typename LeafT,
typename BranchT>
int
126 std::vector<int> &k_indices,
127 std::vector<float> &k_sqr_distances)
129 const PointT search_point = this->getPointByIndex (index);
130 return (nearestKSearch (search_point, k, k_indices, k_sqr_distances));
134 template<
typename Po
intT,
typename LeafT,
typename BranchT>
void
139 assert(this->leafCount_>0);
140 assert (
isFinite (p_q) &&
"Invalid (NaN, Inf) point coordinates given to nearestKSearch!");
143 key.
x = key.
y = key.
z = 0;
145 approxNearestSearchRecursive (p_q, this->rootNode_, key, 1, result_index, sqr_distance);
151 template<
typename Po
intT,
typename LeafT,
typename BranchT>
void
155 const PointT searchPoint = this->getPointByIndex (query_index);
157 return (approxNearestSearch (searchPoint, result_index, sqr_distance));
161 template<
typename Po
intT,
typename LeafT,
typename BranchT>
int
163 std::vector<int> &k_indices,
164 std::vector<float> &k_sqr_distances,
165 unsigned int max_nn)
const
167 assert (
isFinite (p_q) &&
"Invalid (NaN, Inf) point coordinates given to nearestKSearch!");
169 key.
x = key.
y = key.
z = 0;
172 k_sqr_distances.clear ();
174 getNeighborsWithinRadiusRecursive (p_q, radius * radius, this->rootNode_, key, 1, k_indices, k_sqr_distances,
177 return (static_cast<int> (k_indices.size ()));
181 template<
typename Po
intT,
typename LeafT,
typename BranchT>
int
183 std::vector<int> &k_indices,
184 std::vector<float> &k_sqr_distances,
185 unsigned int max_nn)
const
187 const PointT search_point = this->getPointByIndex (index);
189 return (radiusSearch (search_point, radius, k_indices, k_sqr_distances, max_nn));
193 template<
typename Po
intT,
typename LeafT,
typename BranchT>
int
195 const Eigen::Vector3f &max_pt,
196 std::vector<int> &k_indices)
const
200 key.
x = key.
y = key.
z = 0;
204 boxSearchRecursive (min_pt, max_pt, this->rootNode_, key, 1, k_indices);
206 return (static_cast<int> (k_indices.size ()));
211 template<
typename Po
intT,
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
216 std::vector<prioBranchQueueEntry> searchEntryHeap;
217 searchEntryHeap.resize (8);
219 unsigned char childIdx;
223 double smallestSquaredDist = squaredSearchRadius;
226 double voxelSquaredDiameter = this->getVoxelSquaredDiameter (treeDepth);
229 for (childIdx = 0; childIdx < 8; childIdx++)
231 if (this->branchHasChild (*node, childIdx))
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)));
240 this->genVoxelCenterFromOctreeKey (searchEntryHeap[childIdx].key, treeDepth, voxelCenter);
243 searchEntryHeap[childIdx].node = this->getBranchChildPtr (*node, childIdx);
244 searchEntryHeap[childIdx].pointDistance = pointSquaredDist (voxelCenter, point);
248 searchEntryHeap[childIdx].pointDistance = numeric_limits<float>::infinity ();
252 std::sort (searchEntryHeap.begin (), searchEntryHeap.end ());
256 while ((!searchEntryHeap.empty ())
257 && (searchEntryHeap.back ().pointDistance
258 < smallestSquaredDist + voxelSquaredDiameter / 4.0 +
sqrt (smallestSquaredDist * voxelSquaredDiameter)
261 const OctreeNode* childNode;
264 childNode = searchEntryHeap.back ().node;
265 newKey = searchEntryHeap.back ().key;
267 if (treeDepth < this->octreeDepth_)
270 smallestSquaredDist = getKNearestNeighborRecursive (point, K, static_cast<const BranchNode*> (childNode), newKey, treeDepth + 1,
271 smallestSquaredDist, pointCandidates);
279 vector<int> decodedPointVector;
281 const LeafNode* childLeaf =
static_cast<const LeafNode*
> (childNode);
284 childLeaf->getData (decodedPointVector);
287 for (i = 0; i < decodedPointVector.size (); i++)
290 const PointT& candidatePoint = this->getPointByIndex (decodedPointVector[i]);
293 squaredDist = pointSquaredDist (candidatePoint, point);
296 if (squaredDist < smallestSquaredDist)
298 prioPointQueueEntry pointEntry;
300 pointEntry.pointDistance_ = squaredDist;
301 pointEntry.pointIdx_ = decodedPointVector[i];
302 pointCandidates.push_back (pointEntry);
306 std::sort (pointCandidates.begin (), pointCandidates.end ());
308 if (pointCandidates.size () >
K)
309 pointCandidates.resize (K);
311 if (pointCandidates.size () ==
K)
312 smallestSquaredDist = pointCandidates.back ().pointDistance_;
315 searchEntryHeap.pop_back ();
318 return (smallestSquaredDist);
322 template<
typename Po
intT,
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
329 unsigned char childIdx;
332 double voxelSquaredDiameter = this->getVoxelSquaredDiameter (treeDepth);
335 for (childIdx = 0; childIdx < 8; childIdx++)
337 if (!this->branchHasChild (*node, childIdx))
340 const OctreeNode* childNode;
341 childNode = this->getBranchChildPtr (*node, childIdx);
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)));
353 this->genVoxelCenterFromOctreeKey (newKey, treeDepth, voxelCenter);
356 squaredDist = pointSquaredDist (static_cast<const PointT&> (voxelCenter), point);
359 if (squaredDist + this->epsilon_
360 <= voxelSquaredDiameter / 4.0 + radiusSquared +
sqrt (voxelSquaredDiameter * radiusSquared))
363 if (treeDepth < this->octreeDepth_)
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))
376 const LeafNode* childLeaf =
static_cast<const LeafNode*
> (childNode);
377 vector<int> decodedPointVector;
380 childLeaf->getData (decodedPointVector);
383 for (i = 0; i < decodedPointVector.size (); i++)
385 const PointT& candidatePoint = this->getPointByIndex (decodedPointVector[i]);
388 squaredDist = pointSquaredDist (candidatePoint, point);
391 if (squaredDist > radiusSquared)
395 k_indices.push_back (decodedPointVector[i]);
396 k_sqr_distances.push_back (squaredDist);
398 if (max_nn != 0 && k_indices.size () ==
static_cast<unsigned int> (max_nn))
407 template<
typename Po
intT,
typename LeafT,
typename BranchT>
void
409 const BranchNode* node,
410 const OctreeKey& key,
411 unsigned int treeDepth,
415 unsigned char childIdx;
416 unsigned char minChildIdx;
417 double minVoxelCenterDistance;
419 OctreeKey minChildKey;
422 const OctreeNode* childNode;
425 minVoxelCenterDistance = numeric_limits<double>::max ();
430 for (childIdx = 0; childIdx < 8; childIdx++)
432 if (!this->branchHasChild (*node, childIdx))
436 double voxelPointDist;
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)));
443 this->genVoxelCenterFromOctreeKey (newKey, treeDepth, voxelCenter);
445 voxelPointDist = pointSquaredDist (voxelCenter, point);
448 if (voxelPointDist >= minVoxelCenterDistance)
451 minVoxelCenterDistance = voxelPointDist;
452 minChildIdx = childIdx;
453 minChildKey = newKey;
457 assert(minChildIdx<8);
459 childNode = this->getBranchChildPtr (*node, minChildIdx);
461 if (treeDepth < this->octreeDepth_)
464 approxNearestSearchRecursive (point, static_cast<const BranchNode*> (childNode), minChildKey, treeDepth + 1, result_index,
472 double smallestSquaredDist;
474 vector<int> decodedPointVector;
476 const LeafNode* childLeaf =
static_cast<const LeafNode*
> (childNode);
478 smallestSquaredDist = numeric_limits<double>::max ();
481 childLeaf->getData (decodedPointVector);
484 for (i = 0; i < decodedPointVector.size (); i++)
486 const PointT& candidatePoint = this->getPointByIndex (decodedPointVector[i]);
489 squaredDist = pointSquaredDist (candidatePoint, point);
492 if (squaredDist >= smallestSquaredDist)
495 result_index = decodedPointVector[i];
496 smallestSquaredDist = squaredDist;
497 sqr_distance =
static_cast<float> (squaredDist);
503 template<
typename Po
intT,
typename LeafT,
typename BranchT>
float
505 const PointT & pointB)
const
507 return (pointA.getVector3fMap () - pointB.getVector3fMap ()).squaredNorm ();
511 template<
typename Po
intT,
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
520 unsigned char childIdx;
523 for (childIdx = 0; childIdx < 8; childIdx++)
526 const OctreeNode* childNode;
527 childNode = this->getBranchChildPtr (*node, childIdx);
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)));
539 Eigen::Vector3f lowerVoxelCorner;
540 Eigen::Vector3f upperVoxelCorner;
542 this->genVoxelBoundsFromOctreeKey (newKey, treeDepth, lowerVoxelCorner, upperVoxelCorner);
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)) ) )
551 if (treeDepth < this->octreeDepth_)
554 boxSearchRecursive (min_pt, max_pt, static_cast<const BranchNode*> (childNode), newKey, treeDepth + 1, k_indices);
560 vector<int> decodedPointVector;
563 const LeafNode* childLeaf =
static_cast<const LeafNode*
> (childNode);
566 childLeaf->getData (decodedPointVector);
569 for (i = 0; i < decodedPointVector.size (); i++)
571 const PointT& candidatePoint = this->getPointByIndex (decodedPointVector[i]);
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)) );
580 k_indices.push_back (decodedPointVector[i]);
588 template<
typename Po
intT,
typename LeafT,
typename BranchT>
int
591 int maxVoxelCount)
const
594 key.
x = key.
y = key.
z = 0;
596 voxelCenterList.clear ();
601 double minX, minY, minZ, maxX, maxY, maxZ;
603 initIntersectedVoxel (origin, direction, minX, minY, minZ, maxX, maxY, maxZ, a);
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);
613 template<
typename Po
intT,
typename LeafT,
typename BranchT>
int
615 Eigen::Vector3f origin, Eigen::Vector3f direction, std::vector<int> &k_indices,
616 int maxVoxelCount)
const
619 key.
x = key.
y = key.
z = 0;
625 double minX, minY, minZ, maxX, maxY, maxZ;
627 initIntersectedVoxel (origin, direction, minX, minY, minZ, maxX, maxY, maxZ, a);
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);
636 template<
typename Po
intT,
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
641 if (maxX < 0.0 || maxY < 0.0 || maxZ < 0.0)
649 this->genLeafNodeCenterFromOctreeKey (key, newPoint);
651 voxelCenterList.push_back (newPoint);
660 double midX = 0.5 * (minX + maxX);
661 double midY = 0.5 * (minY + maxY);
662 double midZ = 0.5 * (minZ + maxZ);
665 int currNode = getFirstIntersectedNode (minX, minY, minZ, midX, midY, midZ);
668 unsigned char childIdx;
669 const OctreeNode *childNode;
675 childIdx =
static_cast<unsigned char> (currNode ^ a);
680 childNode = this->getBranchChildPtr (static_cast<const BranchNode&> (*node), childIdx);
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)));
695 voxelCount += getIntersectedVoxelCentersRecursive (minX, minY, minZ, midX, midY, midZ, a, childNode,
696 childKey, voxelCenterList, maxVoxelCount);
697 currNode = getNextIntersectedNode (midX, midY, midZ, 4, 2, 1);
702 voxelCount += getIntersectedVoxelCentersRecursive (minX, minY, midZ, midX, midY, maxZ, a, childNode,
703 childKey, voxelCenterList, maxVoxelCount);
704 currNode = getNextIntersectedNode (midX, midY, maxZ, 5, 3, 8);
709 voxelCount += getIntersectedVoxelCentersRecursive (minX, midY, minZ, midX, maxY, midZ, a, childNode,
710 childKey, voxelCenterList, maxVoxelCount);
711 currNode = getNextIntersectedNode (midX, maxY, midZ, 6, 8, 3);
716 voxelCount += getIntersectedVoxelCentersRecursive (minX, midY, midZ, midX, maxY, maxZ, a, childNode,
717 childKey, voxelCenterList, maxVoxelCount);
718 currNode = getNextIntersectedNode (midX, maxY, maxZ, 7, 8, 8);
723 voxelCount += getIntersectedVoxelCentersRecursive (midX, minY, minZ, maxX, midY, midZ, a, childNode,
724 childKey, voxelCenterList, maxVoxelCount);
725 currNode = getNextIntersectedNode (maxX, midY, midZ, 8, 6, 5);
730 voxelCount += getIntersectedVoxelCentersRecursive (midX, minY, midZ, maxX, midY, maxZ, a, childNode,
731 childKey, voxelCenterList, maxVoxelCount);
732 currNode = getNextIntersectedNode (maxX, midY, maxZ, 8, 7, 8);
737 voxelCount += getIntersectedVoxelCentersRecursive (midX, midY, minZ, maxX, maxY, midZ, a, childNode,
738 childKey, voxelCenterList, maxVoxelCount);
739 currNode = getNextIntersectedNode (maxX, maxY, midZ, 8, 8, 7);
744 voxelCount += getIntersectedVoxelCentersRecursive (midX, midY, midZ, maxX, maxY, maxZ, a, childNode,
745 childKey, voxelCenterList, maxVoxelCount);
749 }
while ((currNode < 8) && (maxVoxelCount <= 0 || voxelCount < maxVoxelCount));
754 template<
typename Po
intT,
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
759 if (maxX < 0.0 || maxY < 0.0 || maxZ < 0.0)
765 const LeafNode* leaf =
static_cast<const LeafNode*
> (node);
777 double midX = 0.5 * (minX + maxX);
778 double midY = 0.5 * (minY + maxY);
779 double midZ = 0.5 * (minZ + maxZ);
782 int currNode = getFirstIntersectedNode (minX, minY, minZ, midX, midY, midZ);
785 unsigned char childIdx;
786 const OctreeNode *childNode;
791 childIdx =
static_cast<unsigned char> (currNode ^ a);
796 childNode = this->getBranchChildPtr (static_cast<const BranchNode&> (*node), childIdx);
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)));
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);
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);
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);
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);
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);
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);
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);
858 voxelCount += getIntersectedVoxelIndicesRecursive (midX, midY, midZ, maxX, maxY, maxZ, a, childNode,
859 childKey, k_indices, maxVoxelCount);
863 }
while ((currNode < 8) && (maxVoxelCount <= 0 || voxelCount < maxVoxelCount));
868 #endif // PCL_OCTREE_SEARCH_IMPL_H_