|
Point Cloud Library (PCL)
1.5.1
|
00001 /* 00002 * Software License Agreement (BSD License) 00003 * 00004 * Point Cloud Library (PCL) - www.pointclouds.org 00005 * Copyright (c) 2010-2011, 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: octree_search.hpp 4702 2012-02-23 09:39:33Z gedikli $ 00037 */ 00038 00039 #ifndef PCL_OCTREE_SEARCH_IMPL_H_ 00040 #define PCL_OCTREE_SEARCH_IMPL_H_ 00041 00042 #include <pcl/point_cloud.h> 00043 #include <pcl/point_types.h> 00044 00045 #include <pcl/common/common.h> 00046 #include <assert.h> 00047 00049 template<typename PointT, typename LeafT, typename OctreeT> 00050 bool 00051 pcl::octree::OctreePointCloudSearch<PointT, LeafT, OctreeT>::voxelSearch (const PointT& point, 00052 std::vector<int>& pointIdx_data) 00053 { 00054 assert (isFinite (point) && "Invalid (NaN, Inf) point coordinates given to nearestKSearch!"); 00055 OctreeKey key; 00056 bool b_success = false; 00057 00058 // generate key 00059 this->genOctreeKeyforPoint (point, key); 00060 00061 LeafT* leaf = this->getLeaf (key); 00062 00063 if (leaf) 00064 { 00065 leaf->getData (pointIdx_data); 00066 b_success = true; 00067 } 00068 00069 return (b_success); 00070 } 00071 00073 template<typename PointT, typename LeafT, typename OctreeT> 00074 bool 00075 pcl::octree::OctreePointCloudSearch<PointT, LeafT, OctreeT>::voxelSearch (const int index, 00076 std::vector<int>& pointIdx_data) 00077 { 00078 const PointT search_point = this->getPointByIndex (index); 00079 return (this->voxelSearch (search_point, pointIdx_data)); 00080 } 00081 00083 template<typename PointT, typename LeafT, typename OctreeT> 00084 int 00085 pcl::octree::OctreePointCloudSearch<PointT, LeafT, OctreeT>::nearestKSearch (const PointT &p_q, int k, 00086 std::vector<int> &k_indices, 00087 std::vector<float> &k_sqr_distances) 00088 { 00089 assert(this->leafCount_>0); 00090 assert (isFinite (p_q) && "Invalid (NaN, Inf) point coordinates given to nearestKSearch!"); 00091 00092 k_indices.clear (); 00093 k_sqr_distances.clear (); 00094 00095 if (k < 1) 00096 return 0; 00097 00098 unsigned int i; 00099 unsigned int resultCount; 00100 00101 prioPointQueueEntry pointEntry; 00102 std::vector<prioPointQueueEntry> pointCandidates; 00103 00104 OctreeKey key; 00105 key.x = key.y = key.z = 0; 00106 00107 // initalize smallest point distance in search with high value 00108 double smallestDist = numeric_limits<double>::max (); 00109 00110 getKNearestNeighborRecursive (p_q, k, this->rootNode_, key, 1, smallestDist, pointCandidates); 00111 00112 resultCount = (unsigned int)pointCandidates.size (); 00113 00114 k_indices.resize (resultCount); 00115 k_sqr_distances.resize (resultCount); 00116 00117 for (i = 0; i < resultCount; ++i) 00118 { 00119 k_indices [i] = pointCandidates [i].pointIdx_; 00120 k_sqr_distances [i] = pointCandidates [i].pointDistance_; 00121 } 00122 00123 return (int)k_indices.size (); 00124 } 00125 00127 template<typename PointT, typename LeafT, typename OctreeT> 00128 int 00129 pcl::octree::OctreePointCloudSearch<PointT, LeafT, OctreeT>::nearestKSearch (int index, int k, 00130 std::vector<int> &k_indices, 00131 std::vector<float> &k_sqr_distances) 00132 { 00133 const PointT search_point = this->getPointByIndex (index); 00134 return (nearestKSearch (search_point, k, k_indices, k_sqr_distances)); 00135 } 00136 00138 template<typename PointT, typename LeafT, typename OctreeT> 00139 void 00140 pcl::octree::OctreePointCloudSearch<PointT, LeafT, OctreeT>::approxNearestSearch (const PointT &p_q, 00141 int &result_index, 00142 float &sqr_distance) 00143 { 00144 assert(this->leafCount_>0); 00145 assert (isFinite (p_q) && "Invalid (NaN, Inf) point coordinates given to nearestKSearch!"); 00146 00147 OctreeKey key; 00148 key.x = key.y = key.z = 0; 00149 00150 approxNearestSearchRecursive (p_q, this->rootNode_, key, 1, result_index, sqr_distance); 00151 00152 return; 00153 } 00154 00156 template<typename PointT, typename LeafT, typename OctreeT> 00157 void 00158 pcl::octree::OctreePointCloudSearch<PointT, LeafT, OctreeT>::approxNearestSearch (int query_index, int &result_index, 00159 float &sqr_distance) 00160 { 00161 const PointT searchPoint = this->getPointByIndex (query_index); 00162 00163 return (approxNearestSearch (searchPoint, result_index, sqr_distance)); 00164 } 00165 00167 template<typename PointT, typename LeafT, typename OctreeT> 00168 int 00169 pcl::octree::OctreePointCloudSearch<PointT, LeafT, OctreeT>::radiusSearch (const PointT &p_q, const double radius, 00170 std::vector<int> &k_indices, 00171 std::vector<float> &k_sqr_distances, 00172 unsigned int max_nn) const 00173 { 00174 assert (isFinite (p_q) && "Invalid (NaN, Inf) point coordinates given to nearestKSearch!"); 00175 OctreeKey key; 00176 key.x = key.y = key.z = 0; 00177 00178 k_indices.clear (); 00179 k_sqr_distances.clear (); 00180 00181 getNeighborsWithinRadiusRecursive (p_q, radius * radius, this->rootNode_, key, 1, k_indices, k_sqr_distances, 00182 max_nn); 00183 00184 return ((int)k_indices.size ()); 00185 } 00186 00188 template<typename PointT, typename LeafT, typename OctreeT> 00189 int 00190 pcl::octree::OctreePointCloudSearch<PointT, LeafT, OctreeT>::radiusSearch (int index, const double radius, 00191 std::vector<int> &k_indices, 00192 std::vector<float> &k_sqr_distances, 00193 unsigned int max_nn) const 00194 { 00195 const PointT search_point = this->getPointByIndex (index); 00196 00197 return (radiusSearch (search_point, radius, k_indices, k_sqr_distances, max_nn)); 00198 } 00199 00201 template<typename PointT, typename LeafT, typename OctreeT> 00202 int 00203 pcl::octree::OctreePointCloudSearch<PointT, LeafT, OctreeT>::boxSearch (const Eigen::Vector3f &min_pt, 00204 const Eigen::Vector3f &max_pt, 00205 std::vector<int> &k_indices) const 00206 { 00207 00208 OctreeKey key; 00209 key.x = key.y = key.z = 0; 00210 00211 k_indices.clear (); 00212 00213 boxSearchRecursive (min_pt, max_pt, this->rootNode_, key, 1, k_indices); 00214 00215 return ((int)k_indices.size ()); 00216 00217 } 00218 00220 template<typename PointT, typename LeafT, typename OctreeT> 00221 double 00222 pcl::octree::OctreePointCloudSearch<PointT, LeafT, OctreeT>::getKNearestNeighborRecursive ( 00223 const PointT & point, unsigned int K, const OctreeBranch* node, const OctreeKey& key, unsigned int treeDepth, 00224 const double squaredSearchRadius, std::vector<prioPointQueueEntry>& pointCandidates) const 00225 { 00226 std::vector<prioBranchQueueEntry> searchEntryHeap; 00227 searchEntryHeap.resize (8); 00228 00229 unsigned char childIdx; 00230 00231 OctreeKey newKey; 00232 00233 double smallestSquaredDist = squaredSearchRadius; 00234 00235 // get spatial voxel information 00236 double voxelSquaredDiameter = this->getVoxelSquaredDiameter (treeDepth); 00237 00238 // iterate over all children 00239 for (childIdx = 0; childIdx < 8; childIdx++) 00240 { 00241 if (this->branchHasChild (*node, childIdx)) 00242 { 00243 PointT voxelCenter; 00244 00245 searchEntryHeap[childIdx].key.x = (key.x << 1) + (!!(childIdx & (1 << 2))); 00246 searchEntryHeap[childIdx].key.y = (key.y << 1) + (!!(childIdx & (1 << 1))); 00247 searchEntryHeap[childIdx].key.z = (key.z << 1) + (!!(childIdx & (1 << 0))); 00248 00249 // generate voxel center point for voxel at key 00250 this->genVoxelCenterFromOctreeKey (searchEntryHeap[childIdx].key, treeDepth, voxelCenter); 00251 00252 // generate new priority queue element 00253 searchEntryHeap[childIdx].node = this->getBranchChild (*node, childIdx); 00254 searchEntryHeap[childIdx].pointDistance = pointSquaredDist (voxelCenter, point); 00255 } 00256 else 00257 { 00258 searchEntryHeap[childIdx].pointDistance = numeric_limits<float>::infinity (); 00259 } 00260 } 00261 00262 std::sort (searchEntryHeap.begin (), searchEntryHeap.end ()); 00263 00264 // iterate over all children in priority queue 00265 // check if the distance to search candidate is smaller than the best point distance (smallestSquaredDist) 00266 while ((!searchEntryHeap.empty ()) 00267 && (searchEntryHeap.back ().pointDistance 00268 < smallestSquaredDist + voxelSquaredDiameter / 4.0 + sqrt (smallestSquaredDist * voxelSquaredDiameter) 00269 - this->epsilon_)) 00270 { 00271 const OctreeNode* childNode; 00272 00273 // read from priority queue element 00274 childNode = searchEntryHeap.back ().node; 00275 newKey = searchEntryHeap.back ().key; 00276 00277 if (treeDepth < this->octreeDepth_) 00278 { 00279 // we have not reached maximum tree depth 00280 smallestSquaredDist = getKNearestNeighborRecursive (point, K, (OctreeBranch*)childNode, newKey, treeDepth + 1, 00281 smallestSquaredDist, pointCandidates); 00282 } 00283 else 00284 { 00285 // we reached leaf node level 00286 00287 float squaredDist; 00288 size_t i; 00289 vector<int> decodedPointVector; 00290 00291 OctreeLeaf* childLeaf = (OctreeLeaf*)childNode; 00292 00293 // decode leaf node into decodedPointVector 00294 childLeaf->getData (decodedPointVector); 00295 00296 // Linearly iterate over all decoded (unsorted) points 00297 for (i = 0; i < decodedPointVector.size (); i++) 00298 { 00299 00300 const PointT& candidatePoint = this->getPointByIndex (decodedPointVector[i]); 00301 00302 // calculate point distance to search point 00303 squaredDist = pointSquaredDist (candidatePoint, point); 00304 00305 // check if a closer match is found 00306 if (squaredDist < smallestSquaredDist) 00307 { 00308 prioPointQueueEntry pointEntry; 00309 00310 pointEntry.pointDistance_ = squaredDist; 00311 pointEntry.pointIdx_ = decodedPointVector[i]; 00312 pointCandidates.push_back (pointEntry); 00313 } 00314 } 00315 00316 std::sort (pointCandidates.begin (), pointCandidates.end ()); 00317 00318 if (pointCandidates.size () > K) 00319 pointCandidates.resize (K); 00320 00321 if (pointCandidates.size () == K) 00322 smallestSquaredDist = pointCandidates.back ().pointDistance_; 00323 } 00324 // pop element from priority queue 00325 searchEntryHeap.pop_back (); 00326 } 00327 00328 return (smallestSquaredDist); 00329 } 00330 00332 template<typename PointT, typename LeafT, typename OctreeT> 00333 void 00334 pcl::octree::OctreePointCloudSearch<PointT, LeafT, OctreeT>::getNeighborsWithinRadiusRecursive ( 00335 const PointT & point, const double radiusSquared, const OctreeBranch* node, const OctreeKey& key, 00336 unsigned int treeDepth, std::vector<int>& k_indices, std::vector<float>& k_sqr_distances, 00337 unsigned int max_nn) const 00338 { 00339 // child iterator 00340 unsigned char childIdx; 00341 00342 // get spatial voxel information 00343 double voxelSquaredDiameter = this->getVoxelSquaredDiameter (treeDepth); 00344 00345 // iterate over all children 00346 for (childIdx = 0; childIdx < 8; childIdx++) 00347 { 00348 if (!this->branchHasChild (*node, childIdx)) 00349 continue; 00350 00351 const OctreeNode* childNode; 00352 childNode = this->getBranchChild (*node, childIdx); 00353 00354 OctreeKey newKey; 00355 PointT voxelCenter; 00356 float squaredDist; 00357 00358 // generate new key for current branch voxel 00359 newKey.x = (key.x << 1) + (!!(childIdx & (1 << 2))); 00360 newKey.y = (key.y << 1) + (!!(childIdx & (1 << 1))); 00361 newKey.z = (key.z << 1) + (!!(childIdx & (1 << 0))); 00362 00363 // generate voxel center point for voxel at key 00364 this->genVoxelCenterFromOctreeKey (newKey, treeDepth, voxelCenter); 00365 00366 // calculate distance to search point 00367 squaredDist = pointSquaredDist ((const PointT &)voxelCenter, point); 00368 00369 // if distance is smaller than search radius 00370 if (squaredDist + this->epsilon_ 00371 <= voxelSquaredDiameter / 4.0 + radiusSquared + sqrt (voxelSquaredDiameter * radiusSquared)) 00372 { 00373 00374 if (treeDepth < this->octreeDepth_) 00375 { 00376 // we have not reached maximum tree depth 00377 getNeighborsWithinRadiusRecursive (point, radiusSquared, (OctreeBranch*)childNode, newKey, treeDepth + 1, 00378 k_indices, k_sqr_distances, max_nn); 00379 if (max_nn != 0 && k_indices.size () == (unsigned int)max_nn) 00380 return; 00381 } 00382 else 00383 { 00384 // we reached leaf node level 00385 00386 size_t i; 00387 OctreeLeaf* childLeaf = (OctreeLeaf*)childNode; 00388 vector<int> decodedPointVector; 00389 00390 // decode leaf node into decodedPointVector 00391 childLeaf->getData (decodedPointVector); 00392 00393 // Linearly iterate over all decoded (unsorted) points 00394 for (i = 0; i < decodedPointVector.size (); i++) 00395 { 00396 const PointT& candidatePoint = this->getPointByIndex (decodedPointVector[i]); 00397 00398 // calculate point distance to search point 00399 squaredDist = pointSquaredDist (candidatePoint, point); 00400 00401 // check if a match is found 00402 if (squaredDist > radiusSquared) 00403 continue; 00404 00405 // add point to result vector 00406 k_indices.push_back (decodedPointVector[i]); 00407 k_sqr_distances.push_back (squaredDist); 00408 00409 if (max_nn != 0 && k_indices.size () == (unsigned int)max_nn) 00410 return; 00411 } 00412 } 00413 } 00414 } 00415 } 00416 00418 template<typename PointT, typename LeafT, typename OctreeT> 00419 void 00420 pcl::octree::OctreePointCloudSearch<PointT, LeafT, OctreeT>::approxNearestSearchRecursive (const PointT & point, 00421 const OctreeBranch* node, 00422 const OctreeKey& key, 00423 unsigned int treeDepth, 00424 int& result_index, 00425 float& sqr_distance) 00426 { 00427 unsigned char childIdx; 00428 unsigned char minChildIdx; 00429 double minVoxelCenterDistance; 00430 00431 OctreeKey minChildKey; 00432 OctreeKey newKey; 00433 00434 const OctreeNode* childNode; 00435 00436 // set minimum voxel distance to maximum value 00437 minVoxelCenterDistance = numeric_limits<double>::max (); 00438 00439 minChildIdx = 0xFF; 00440 00441 // iterate over all children 00442 for (childIdx = 0; childIdx < 8; childIdx++) 00443 { 00444 if (!this->branchHasChild (*node, childIdx)) 00445 continue; 00446 00447 PointT voxelCenter; 00448 double voxelPointDist; 00449 00450 newKey.x = (key.x << 1) + (!!(childIdx & (1 << 2))); 00451 newKey.y = (key.y << 1) + (!!(childIdx & (1 << 1))); 00452 newKey.z = (key.z << 1) + (!!(childIdx & (1 << 0))); 00453 00454 // generate voxel center point for voxel at key 00455 this->genVoxelCenterFromOctreeKey (newKey, treeDepth, voxelCenter); 00456 00457 voxelPointDist = pointSquaredDist (voxelCenter, point); 00458 00459 // search for child voxel with shortest distance to search point 00460 if (voxelPointDist >= minVoxelCenterDistance) 00461 continue; 00462 00463 minVoxelCenterDistance = voxelPointDist; 00464 minChildIdx = childIdx; 00465 minChildKey = newKey; 00466 } 00467 00468 // make sure we found at least one branch child 00469 assert(minChildIdx<8); 00470 00471 childNode = this->getBranchChild (*node, minChildIdx); 00472 00473 if (treeDepth < this->octreeDepth_) 00474 { 00475 // we have not reached maximum tree depth 00476 approxNearestSearchRecursive (point, (OctreeBranch*)childNode, minChildKey, treeDepth + 1, result_index, 00477 sqr_distance); 00478 } 00479 else 00480 { 00481 // we reached leaf node level 00482 00483 double squaredDist; 00484 double smallestSquaredDist; 00485 size_t i; 00486 vector<int> decodedPointVector; 00487 00488 OctreeLeaf* childLeaf = (OctreeLeaf*)childNode; 00489 00490 smallestSquaredDist = numeric_limits<double>::max (); 00491 00492 // decode leaf node into decodedPointVector 00493 childLeaf->getData (decodedPointVector); 00494 00495 // Linearly iterate over all decoded (unsorted) points 00496 for (i = 0; i < decodedPointVector.size (); i++) 00497 { 00498 const PointT& candidatePoint = this->getPointByIndex (decodedPointVector[i]); 00499 00500 // calculate point distance to search point 00501 squaredDist = pointSquaredDist (candidatePoint, point); 00502 00503 // check if a closer match is found 00504 if (squaredDist >= smallestSquaredDist) 00505 continue; 00506 00507 result_index = decodedPointVector[i]; 00508 smallestSquaredDist = squaredDist; 00509 sqr_distance = (float)squaredDist; 00510 } 00511 } 00512 } 00513 00515 template<typename PointT, typename LeafT, typename OctreeT> float 00516 pcl::octree::OctreePointCloudSearch<PointT, LeafT, OctreeT>::pointSquaredDist (const PointT & pointA, 00517 const PointT & pointB) const 00518 { 00519 return (pointA.getVector3fMap () - pointB.getVector3fMap ()).squaredNorm (); 00520 } 00521 00523 template<typename PointT, typename LeafT, typename OctreeT> 00524 void 00525 pcl::octree::OctreePointCloudSearch<PointT, LeafT, OctreeT>::boxSearchRecursive (const Eigen::Vector3f &min_pt, 00526 const Eigen::Vector3f &max_pt, 00527 const OctreeBranch* node, 00528 const OctreeKey& key, 00529 unsigned int treeDepth, 00530 std::vector<int>& k_indices) const 00531 { 00532 // child iterator 00533 unsigned char childIdx; 00534 00535 // iterate over all children 00536 for (childIdx = 0; childIdx < 8; childIdx++) 00537 { 00538 if (!this->branchHasChild (*node, childIdx)) 00539 continue; 00540 00541 const OctreeNode* childNode; 00542 childNode = this->getBranchChild (*node, childIdx); 00543 00544 OctreeKey newKey; 00545 // generate new key for current branch voxel 00546 newKey.x = (key.x << 1) + (!!(childIdx & (1 << 2))); 00547 newKey.y = (key.y << 1) + (!!(childIdx & (1 << 1))); 00548 newKey.z = (key.z << 1) + (!!(childIdx & (1 << 0))); 00549 00550 // voxel corners 00551 Eigen::Vector3f lowerVoxelCorner; 00552 Eigen::Vector3f upperVoxelCorner; 00553 // get voxel coordinates 00554 this->genVoxelBoundsFromOctreeKey (newKey, treeDepth, lowerVoxelCorner, upperVoxelCorner); 00555 00556 // test if search region overlap with voxel space 00557 00558 if ( !( (lowerVoxelCorner (0) > max_pt (0)) || (min_pt (0) > upperVoxelCorner(0)) || 00559 (lowerVoxelCorner (1) > max_pt (1)) || (min_pt (1) > upperVoxelCorner(1)) || 00560 (lowerVoxelCorner (2) > max_pt (2)) || (min_pt (2) > upperVoxelCorner(2)) ) ) 00561 { 00562 00563 if (treeDepth < this->octreeDepth_) 00564 { 00565 // we have not reached maximum tree depth 00566 boxSearchRecursive (min_pt, max_pt, (OctreeBranch*)childNode, newKey, treeDepth + 1, k_indices); 00567 } 00568 else 00569 { 00570 // we reached leaf node level 00571 size_t i; 00572 vector<int> decodedPointVector; 00573 bool bInBox; 00574 00575 OctreeLeaf* childLeaf = (OctreeLeaf*)childNode; 00576 00577 // decode leaf node into decodedPointVector 00578 childLeaf->getData (decodedPointVector); 00579 00580 // Linearly iterate over all decoded (unsorted) points 00581 for (i = 0; i < decodedPointVector.size (); i++) 00582 { 00583 const PointT& candidatePoint = this->getPointByIndex (decodedPointVector[i]); 00584 00585 // check if point falls within search box 00586 bInBox = ( (candidatePoint.x > min_pt (0)) && (candidatePoint.x < max_pt (0)) && 00587 (candidatePoint.y > min_pt (1)) && (candidatePoint.y < max_pt (1)) && 00588 (candidatePoint.z > min_pt (2)) && (candidatePoint.z < max_pt (2)) ); 00589 00590 if (bInBox) 00591 // add to result vector 00592 k_indices.push_back (decodedPointVector[i]); 00593 } 00594 00595 } 00596 00597 } 00598 } 00599 } 00600 00602 template<typename PointT, typename LeafT, typename OctreeT> 00603 int 00604 pcl::octree::OctreePointCloudSearch<PointT, LeafT, OctreeT>::getIntersectedVoxelCenters ( 00605 Eigen::Vector3f origin, Eigen::Vector3f direction, AlignedPointTVector &voxelCenterList) const 00606 { 00607 OctreeKey key; 00608 key.x = key.y = key.z = 0; 00609 00610 voxelCenterList.clear (); 00611 00612 // Voxel childIdx remapping 00613 unsigned char a = 0; 00614 00615 double minX, minY, minZ, maxX, maxY, maxZ; 00616 00617 initIntersectedVoxel (origin, direction, minX, minY, minZ, maxX, maxY, maxZ, a); 00618 00619 if (max (max (minX, minY), minZ) < min (min (maxX, maxY), maxZ)) 00620 return getIntersectedVoxelCentersRecursive (minX, minY, minZ, maxX, maxY, maxZ, a, this->rootNode_, key, 00621 voxelCenterList); 00622 00623 return (0); 00624 } 00625 00627 template<typename PointT, typename LeafT, typename OctreeT> 00628 int 00629 pcl::octree::OctreePointCloudSearch<PointT, LeafT, OctreeT>::getIntersectedVoxelIndices ( 00630 Eigen::Vector3f origin, Eigen::Vector3f direction, std::vector<int> &k_indices) const 00631 { 00632 OctreeKey key; 00633 key.x = key.y = key.z = 0; 00634 00635 k_indices.clear (); 00636 00637 // Voxel childIdx remapping 00638 unsigned char a = 0; 00639 double minX, minY, minZ, maxX, maxY, maxZ; 00640 00641 initIntersectedVoxel (origin, direction, minX, minY, minZ, maxX, maxY, maxZ, a); 00642 00643 if (max (max (minX, minY), minZ) < min (min (maxX, maxY), maxZ)) 00644 return getIntersectedVoxelIndicesRecursive (minX, minY, minZ, maxX, maxY, maxZ, a, this->rootNode_, key, 00645 k_indices); 00646 return (0); 00647 } 00648 00650 template<typename PointT, typename LeafT, typename OctreeT> 00651 int 00652 pcl::octree::OctreePointCloudSearch<PointT, LeafT, OctreeT>::getIntersectedVoxelCentersRecursive ( 00653 double minX, double minY, double minZ, double maxX, double maxY, double maxZ, unsigned char a, 00654 const OctreeNode* node, const OctreeKey& key, AlignedPointTVector &voxelCenterList) const 00655 { 00656 if (maxX < 0.0 || maxY < 0.0 || maxZ < 0.0) 00657 return (0); 00658 00659 // If leaf node, get voxel center and increment intersection count 00660 if (node->getNodeType () == LEAF_NODE) 00661 { 00662 PointT newPoint; 00663 00664 this->genLeafNodeCenterFromOctreeKey (key, newPoint); 00665 00666 voxelCenterList.push_back (newPoint); 00667 00668 return (1); 00669 } 00670 00671 // Voxel intersection count for branches children 00672 int voxelCount = 0; 00673 00674 // Voxel mid lines 00675 double midX = 0.5 * (minX + maxX); 00676 double midY = 0.5 * (minY + maxY); 00677 double midZ = 0.5 * (minZ + maxZ); 00678 00679 // First voxel node ray will intersect 00680 int currNode = getFirstIntersectedNode (minX, minY, minZ, midX, midY, midZ); 00681 00682 // Child index, node and key 00683 unsigned char childIdx; 00684 const OctreeNode *childNode; 00685 OctreeKey childKey; 00686 00687 do 00688 { 00689 if (currNode != 0) 00690 childIdx = currNode ^ a; 00691 else 00692 childIdx = a; 00693 00694 // childNode == 0 if childNode doesn't exist 00695 childNode = this->getBranchChild ((OctreeBranch&)*node, childIdx); 00696 00697 // Generate new key for current branch voxel 00698 childKey.x = (key.x << 1) | (!!(childIdx & (1 << 2))); 00699 childKey.y = (key.y << 1) | (!!(childIdx & (1 << 1))); 00700 childKey.z = (key.z << 1) | (!!(childIdx & (1 << 0))); 00701 00702 // Recursively call each intersected child node, selecting the next 00703 // node intersected by the ray. Children that do not intersect will 00704 // not be traversed. 00705 00706 switch (currNode) 00707 { 00708 case 0: 00709 if (childNode) 00710 voxelCount += getIntersectedVoxelCentersRecursive (minX, minY, minZ, midX, midY, midZ, a, childNode, 00711 childKey, voxelCenterList); 00712 currNode = getNextIntersectedNode (midX, midY, midZ, 4, 2, 1); 00713 break; 00714 00715 case 1: 00716 if (childNode) 00717 voxelCount += getIntersectedVoxelCentersRecursive (minX, minY, midZ, midX, midY, maxZ, a, childNode, 00718 childKey, voxelCenterList); 00719 currNode = getNextIntersectedNode (midX, midY, maxZ, 5, 3, 8); 00720 break; 00721 00722 case 2: 00723 if (childNode) 00724 voxelCount += getIntersectedVoxelCentersRecursive (minX, midY, minZ, midX, maxY, midZ, a, childNode, 00725 childKey, voxelCenterList); 00726 currNode = getNextIntersectedNode (midX, maxY, midZ, 6, 8, 3); 00727 break; 00728 00729 case 3: 00730 if (childNode) 00731 voxelCount += getIntersectedVoxelCentersRecursive (minX, midY, midZ, midX, maxY, maxZ, a, childNode, 00732 childKey, voxelCenterList); 00733 currNode = getNextIntersectedNode (midX, maxY, maxZ, 7, 8, 8); 00734 break; 00735 00736 case 4: 00737 if (childNode) 00738 voxelCount += getIntersectedVoxelCentersRecursive (midX, minY, minZ, maxX, midY, midZ, a, childNode, 00739 childKey, voxelCenterList); 00740 currNode = getNextIntersectedNode (maxX, midY, midZ, 8, 6, 5); 00741 break; 00742 00743 case 5: 00744 if (childNode) 00745 voxelCount += getIntersectedVoxelCentersRecursive (midX, minY, midZ, maxX, midY, maxZ, a, childNode, 00746 childKey, voxelCenterList); 00747 currNode = getNextIntersectedNode (maxX, midY, maxZ, 8, 7, 8); 00748 break; 00749 00750 case 6: 00751 if (childNode) 00752 voxelCount += getIntersectedVoxelCentersRecursive (midX, midY, minZ, maxX, maxY, midZ, a, childNode, 00753 childKey, voxelCenterList); 00754 currNode = getNextIntersectedNode (maxX, maxY, midZ, 8, 8, 7); 00755 break; 00756 00757 case 7: 00758 if (childNode) 00759 voxelCount += getIntersectedVoxelCentersRecursive (midX, midY, midZ, maxX, maxY, maxZ, a, childNode, 00760 childKey, voxelCenterList); 00761 currNode = 8; 00762 break; 00763 } 00764 } while (currNode < 8); 00765 return (voxelCount); 00766 } 00767 00769 template<typename PointT, typename LeafT, typename OctreeT> 00770 int 00771 pcl::octree::OctreePointCloudSearch<PointT, LeafT, OctreeT>::getIntersectedVoxelIndicesRecursive ( 00772 double minX, double minY, double minZ, double maxX, double maxY, double maxZ, unsigned char a, 00773 const OctreeNode* node, const OctreeKey& key, std::vector<int> &k_indices) const 00774 { 00775 if (maxX < 0.0 || maxY < 0.0 || maxZ < 0.0) 00776 return (0); 00777 00778 // If leaf node, get voxel center and increment intersection count 00779 if (node->getNodeType () == LEAF_NODE) 00780 { 00781 OctreeLeaf* leaf = (OctreeLeaf*)node; 00782 vector<int> indices; 00783 00784 // decode leaf node into decodedPointVector 00785 leaf->getData (indices); 00786 for (size_t i = 0; i < indices.size (); i++) 00787 { 00788 k_indices.push_back (indices[i]); 00789 } 00790 00791 return (1); 00792 } 00793 00794 // Voxel intersection count for branches children 00795 int voxelCount = 0; 00796 00797 // Voxel mid lines 00798 double midX = 0.5 * (minX + maxX); 00799 double midY = 0.5 * (minY + maxY); 00800 double midZ = 0.5 * (minZ + maxZ); 00801 00802 // First voxel node ray will intersect 00803 int currNode = getFirstIntersectedNode (minX, minY, minZ, midX, midY, midZ); 00804 00805 // Child index, node and key 00806 unsigned char childIdx; 00807 const OctreeNode *childNode; 00808 OctreeKey childKey; 00809 do 00810 { 00811 if (currNode != 0) 00812 childIdx = currNode ^ a; 00813 else 00814 childIdx = a; 00815 00816 // childNode == 0 if childNode doesn't exist 00817 childNode = this->getBranchChild ((OctreeBranch&)*node, childIdx); 00818 // Generate new key for current branch voxel 00819 childKey.x = (key.x << 1) | (!!(childIdx & (1 << 2))); 00820 childKey.y = (key.y << 1) | (!!(childIdx & (1 << 1))); 00821 childKey.z = (key.z << 1) | (!!(childIdx & (1 << 0))); 00822 00823 // Recursively call each intersected child node, selecting the next 00824 // node intersected by the ray. Children that do not intersect will 00825 // not be traversed. 00826 switch (currNode) 00827 { 00828 case 0: 00829 if (childNode) 00830 voxelCount += getIntersectedVoxelIndicesRecursive (minX, minY, minZ, midX, midY, midZ, a, childNode, 00831 childKey, k_indices); 00832 currNode = getNextIntersectedNode (midX, midY, midZ, 4, 2, 1); 00833 break; 00834 00835 case 1: 00836 if (childNode) 00837 voxelCount += getIntersectedVoxelIndicesRecursive (minX, minY, midZ, midX, midY, maxZ, a, childNode, 00838 childKey, k_indices); 00839 currNode = getNextIntersectedNode (midX, midY, maxZ, 5, 3, 8); 00840 break; 00841 00842 case 2: 00843 if (childNode) 00844 voxelCount += getIntersectedVoxelIndicesRecursive (minX, midY, minZ, midX, maxY, midZ, a, childNode, 00845 childKey, k_indices); 00846 currNode = getNextIntersectedNode (midX, maxY, midZ, 6, 8, 3); 00847 break; 00848 00849 case 3: 00850 if (childNode) 00851 voxelCount += getIntersectedVoxelIndicesRecursive (minX, midY, midZ, midX, maxY, maxZ, a, childNode, 00852 childKey, k_indices); 00853 currNode = getNextIntersectedNode (midX, maxY, maxZ, 7, 8, 8); 00854 break; 00855 00856 case 4: 00857 if (childNode) 00858 voxelCount += getIntersectedVoxelIndicesRecursive (midX, minY, minZ, maxX, midY, midZ, a, childNode, 00859 childKey, k_indices); 00860 currNode = getNextIntersectedNode (maxX, midY, midZ, 8, 6, 5); 00861 break; 00862 00863 case 5: 00864 if (childNode) 00865 voxelCount += getIntersectedVoxelIndicesRecursive (midX, minY, midZ, maxX, midY, maxZ, a, childNode, 00866 childKey, k_indices); 00867 currNode = getNextIntersectedNode (maxX, midY, maxZ, 8, 7, 8); 00868 break; 00869 00870 case 6: 00871 if (childNode) 00872 voxelCount += getIntersectedVoxelIndicesRecursive (midX, midY, minZ, maxX, maxY, midZ, a, childNode, 00873 childKey, k_indices); 00874 currNode = getNextIntersectedNode (maxX, maxY, midZ, 8, 8, 7); 00875 break; 00876 00877 case 7: 00878 if (childNode) 00879 voxelCount += getIntersectedVoxelIndicesRecursive (midX, midY, midZ, maxX, maxY, maxZ, a, childNode, 00880 childKey, k_indices); 00881 currNode = 8; 00882 break; 00883 } 00884 } while (currNode < 8); 00885 00886 return (voxelCount); 00887 } 00888 00889 #endif // PCL_OCTREE_SEARCH_IMPL_H_
1.8.0