|
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_pointcloud.hpp 4702 2012-02-23 09:39:33Z gedikli $ 00037 */ 00038 00039 #ifndef OCTREE_POINTCLOUD_HPP_ 00040 #define OCTREE_POINTCLOUD_HPP_ 00041 00042 #include <vector> 00043 #include <assert.h> 00044 00045 #include "pcl/common/common.h" 00046 00048 template<typename PointT, typename LeafT, typename OctreeT> 00049 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::OctreePointCloud (const double resolution) : 00050 OctreeT (), epsilon_ (0), resolution_ (resolution), minX_ (0.0f), maxX_ (resolution), minY_ (0.0f), 00051 maxY_ (resolution), minZ_ (0.0f), maxZ_ (resolution), maxKeys_ (1), boundingBoxDefined_ (false) 00052 { 00053 assert ( resolution > 0.0f ); 00054 input_ = PointCloudConstPtr (); 00055 } 00056 00058 template<typename PointT, typename LeafT, typename OctreeT> 00059 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::~OctreePointCloud () 00060 { 00061 } 00062 00064 template<typename PointT, typename LeafT, typename OctreeT> void 00065 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::addPointsFromInputCloud () 00066 { 00067 size_t i; 00068 00069 assert (this->leafCount_==0); 00070 if (indices_) 00071 { 00072 for (std::vector<int>::const_iterator current = indices_->begin (); current != indices_->end (); ++current) 00073 { 00074 if (isFinite (input_->points[*current])) 00075 { 00076 assert( (*current>=0) && (*current<(int)input_->points.size ())); 00077 00078 // add points to octree 00079 this->addPointIdx (*current); 00080 } 00081 } 00082 } 00083 else 00084 { 00085 for (i = 0; i < input_->points.size (); i++) 00086 { 00087 if (isFinite (input_->points[i])) 00088 { 00089 // add points to octree 00090 this->addPointIdx ((unsigned int)i); 00091 } 00092 } 00093 } 00094 } 00095 00097 template<typename PointT, typename LeafT, typename OctreeT> void 00098 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::addPointFromCloud (const int pointIdx_arg, IndicesPtr indices_arg) 00099 { 00100 this->addPointIdx (pointIdx_arg); 00101 if (indices_arg) 00102 indices_arg->push_back (pointIdx_arg); 00103 } 00104 00106 template<typename PointT, typename LeafT, typename OctreeT> void 00107 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::addPointToCloud (const PointT& point_arg, PointCloudPtr cloud_arg) 00108 { 00109 assert (cloud_arg==input_); 00110 00111 cloud_arg->points.push_back (point_arg); 00112 00113 this->addPointIdx ((const int)cloud_arg->points.size () - 1); 00114 } 00115 00117 template<typename PointT, typename LeafT, typename OctreeT> void 00118 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::addPointToCloud (const PointT& point_arg, PointCloudPtr cloud_arg, 00119 IndicesPtr indices_arg) 00120 { 00121 assert (cloud_arg==input_); 00122 assert (indices_arg==indices_); 00123 00124 cloud_arg->points.push_back (point_arg); 00125 00126 this->addPointFromCloud ((const int)cloud_arg->points.size () - 1, indices_arg); 00127 } 00128 00130 template<typename PointT, typename LeafT, typename OctreeT> bool 00131 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::isVoxelOccupiedAtPoint (const PointT& point_arg) const 00132 { 00133 OctreeKey key; 00134 00135 // generate key for point 00136 this->genOctreeKeyforPoint (point_arg, key); 00137 00138 // search for key in octree 00139 return (this->existLeaf (key)); 00140 } 00141 00143 template<typename PointT, typename LeafT, typename OctreeT> bool 00144 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::isVoxelOccupiedAtPoint (const int& pointIdx_arg) const 00145 { 00146 // retrieve point from input cloud 00147 const PointT& point = this->input_->points[pointIdx_arg]; 00148 00149 // search for voxel at point in octree 00150 return (this->isVoxelOccupiedAtPoint (point)); 00151 } 00152 00154 template<typename PointT, typename LeafT, typename OctreeT> bool 00155 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::isVoxelOccupiedAtPoint ( 00156 const double pointX_arg, const double pointY_arg, const double pointZ_arg) const 00157 { 00158 OctreeKey key; 00159 00160 // generate key for point 00161 this->genOctreeKeyforPoint (pointX_arg, pointY_arg, pointZ_arg, key); 00162 00163 return (this->existLeaf (key)); 00164 } 00165 00167 template<typename PointT, typename LeafT, typename OctreeT> void 00168 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::deleteVoxelAtPoint (const PointT& point_arg) 00169 { 00170 OctreeKey key; 00171 00172 // generate key for point 00173 this->genOctreeKeyforPoint (point_arg, key); 00174 00175 this->removeLeaf (key); 00176 } 00177 00179 template<typename PointT, typename LeafT, typename OctreeT> void 00180 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::deleteVoxelAtPoint (const int& pointIdx_arg) 00181 { 00182 // retrieve point from input cloud 00183 const PointT& point = this->input_->points[pointIdx_arg]; 00184 00185 // delete leaf at point 00186 this->deleteVoxelAtPoint (point); 00187 } 00188 00190 template<typename PointT, typename LeafT, typename OctreeT> int 00191 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::getOccupiedVoxelCenters ( 00192 std::vector<PointT, Eigen::aligned_allocator<PointT> > &voxelCenterList_arg) const 00193 { 00194 OctreeKey key; 00195 key.x = key.y = key.z = 0; 00196 00197 voxelCenterList_arg.clear (); 00198 00199 return getOccupiedVoxelCentersRecursive (this->rootNode_, key, voxelCenterList_arg); 00200 00201 } 00202 00204 template<typename PointT, typename LeafT, typename OctreeT> int 00205 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::getApproxIntersectedVoxelCentersBySegment ( 00206 const Eigen::Vector3f& origin, 00207 const Eigen::Vector3f& end, 00208 AlignedPointTVector &voxel_center_list, 00209 float precision) 00210 { 00211 Eigen::Vector3f direction = end - origin; 00212 float norm = direction.norm (); 00213 direction.normalize (); 00214 00215 const float step_size = (const float)resolution_ * precision; 00216 // Ensure we get at least one step for the first voxel. 00217 const int nsteps = std::max (1, (int) (norm / step_size)); 00218 00219 OctreeKey prev_key; 00220 prev_key.x = prev_key.y = prev_key.z = -1; 00221 00222 // Walk along the line segment with small steps. 00223 for (int i = 0; i < nsteps; ++i) 00224 { 00225 Eigen::Vector3f p = origin + (direction * step_size * (const float)i); 00226 00227 PointT octree_p; 00228 octree_p.x = p.x (); 00229 octree_p.y = p.y (); 00230 octree_p.z = p.z (); 00231 00232 OctreeKey key; 00233 this->genOctreeKeyforPoint (octree_p, key); 00234 00235 // Not a new key, still the same voxel. 00236 if (key == prev_key) 00237 continue; 00238 00239 prev_key = key; 00240 00241 PointT center; 00242 genLeafNodeCenterFromOctreeKey (key, center); 00243 voxel_center_list.push_back (center); 00244 } 00245 00246 OctreeKey end_key; 00247 PointT end_p; 00248 end_p.x = end.x (); 00249 end_p.y = end.y (); 00250 end_p.z = end.z (); 00251 this->genOctreeKeyforPoint (end_p, end_key); 00252 if (!(end_key == prev_key)) 00253 { 00254 PointT center; 00255 genLeafNodeCenterFromOctreeKey (end_key, center); 00256 voxel_center_list.push_back (center); 00257 } 00258 00259 return ((int)voxel_center_list.size ()); 00260 } 00261 00263 template<typename PointT, typename LeafT, typename OctreeT> void 00264 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::defineBoundingBox () 00265 { 00266 00267 double minX, minY, minZ, maxX, maxY, maxZ; 00268 00269 PointT min_pt; 00270 PointT max_pt; 00271 00272 // bounding box cannot be changed once the octree contains elements 00273 assert (this->leafCount_ == 0); 00274 00275 pcl::getMinMax3D (*input_, min_pt, max_pt); 00276 00277 float minValue = std::numeric_limits<float>::epsilon () * 512.0f; 00278 00279 minX = min_pt.x; 00280 minY = min_pt.y; 00281 minZ = min_pt.z; 00282 00283 maxX = max_pt.x + minValue; 00284 maxY = max_pt.y + minValue; 00285 maxZ = max_pt.z + minValue; 00286 00287 // generate bit masks for octree 00288 defineBoundingBox (minX, minY, minZ, maxX, maxY, maxZ); 00289 } 00290 00292 template<typename PointT, typename LeafT, typename OctreeT> void 00293 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::defineBoundingBox (const double minX_arg, 00294 const double minY_arg, 00295 const double minZ_arg, 00296 const double maxX_arg, 00297 const double maxY_arg, const double maxZ_arg) 00298 { 00299 // bounding box cannot be changed once the octree contains elements 00300 assert (this->leafCount_ == 0); 00301 00302 assert (maxX_arg >= minX_arg); 00303 assert (maxY_arg >= minY_arg); 00304 assert (maxZ_arg >= minZ_arg); 00305 00306 minX_ = minX_arg; 00307 maxX_ = maxX_arg; 00308 00309 minY_ = minY_arg; 00310 maxY_ = maxY_arg; 00311 00312 minZ_ = minZ_arg; 00313 maxZ_ = maxZ_arg; 00314 00315 minX_ = min (minX_, maxX_); 00316 minY_ = min (minY_, maxY_); 00317 minZ_ = min (minZ_, maxZ_); 00318 00319 maxX_ = max (minX_, maxX_); 00320 maxY_ = max (minY_, maxY_); 00321 maxZ_ = max (minZ_, maxZ_); 00322 00323 // generate bit masks for octree 00324 getKeyBitSize (); 00325 00326 boundingBoxDefined_ = true; 00327 } 00328 00330 template<typename PointT, typename LeafT, typename OctreeT> void 00331 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::defineBoundingBox ( 00332 const double maxX_arg, const double maxY_arg, const double maxZ_arg) 00333 { 00334 // bounding box cannot be changed once the octree contains elements 00335 assert (this->leafCount_ == 0); 00336 00337 assert (maxX_arg >= 0.0f); 00338 assert (maxY_arg >= 0.0f); 00339 assert (maxZ_arg >= 0.0f); 00340 00341 minX_ = 0.0f; 00342 maxX_ = maxX_arg; 00343 00344 minY_ = 0.0f; 00345 maxY_ = maxY_arg; 00346 00347 minZ_ = 0.0f; 00348 maxZ_ = maxZ_arg; 00349 00350 minX_ = min (minX_, maxX_); 00351 minY_ = min (minY_, maxY_); 00352 minZ_ = min (minZ_, maxZ_); 00353 00354 maxX_ = max (minX_, maxX_); 00355 maxY_ = max (minY_, maxY_); 00356 maxZ_ = max (minZ_, maxZ_); 00357 00358 // generate bit masks for octree 00359 getKeyBitSize (); 00360 00361 boundingBoxDefined_ = true; 00362 } 00363 00365 template<typename PointT, typename LeafT, typename OctreeT> void 00366 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::defineBoundingBox (const double cubeLen_arg) 00367 { 00368 // bounding box cannot be changed once the octree contains elements 00369 assert (this->leafCount_ == 0); 00370 00371 assert (cubeLen_arg >= 0.0f); 00372 00373 minX_ = 0.0f; 00374 maxX_ = cubeLen_arg; 00375 00376 minY_ = 0.0f; 00377 maxY_ = cubeLen_arg; 00378 00379 minZ_ = 0.0f; 00380 maxZ_ = cubeLen_arg; 00381 00382 minX_ = min (minX_, maxX_); 00383 minY_ = min (minY_, maxY_); 00384 minZ_ = min (minZ_, maxZ_); 00385 00386 maxX_ = max (minX_, maxX_); 00387 maxY_ = max (minY_, maxY_); 00388 maxZ_ = max (minZ_, maxZ_); 00389 00390 // generate bit masks for octree 00391 getKeyBitSize (); 00392 00393 boundingBoxDefined_ = true; 00394 } 00395 00397 template<typename PointT, typename LeafT, typename OctreeT> void 00398 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::getBoundingBox ( 00399 double& minX_arg, double& minY_arg, double& minZ_arg, 00400 double& maxX_arg, double& maxY_arg, double& maxZ_arg) const 00401 { 00402 minX_arg = minX_; 00403 minY_arg = minY_; 00404 minZ_arg = minZ_; 00405 00406 maxX_arg = maxX_; 00407 maxY_arg = maxY_; 00408 maxZ_arg = maxZ_; 00409 } 00410 00412 template<typename PointT, typename LeafT, typename OctreeT> void 00413 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::adoptBoundingBoxToPoint (const PointT& pointIdx_arg) 00414 { 00415 00416 const float minValue = std::numeric_limits<float>::epsilon(); 00417 00418 // increase octree size until point fits into bounding box 00419 while (true) 00420 { 00421 bool bLowerBoundViolationX = (pointIdx_arg.x < minX_); 00422 bool bLowerBoundViolationY = (pointIdx_arg.y < minY_); 00423 bool bLowerBoundViolationZ = (pointIdx_arg.z < minZ_); 00424 00425 bool bUpperBoundViolationX = (pointIdx_arg.x >= maxX_); 00426 bool bUpperBoundViolationY = (pointIdx_arg.y >= maxY_); 00427 bool bUpperBoundViolationZ = (pointIdx_arg.z >= maxZ_); 00428 00429 // do we violate any bounds? 00430 if (bLowerBoundViolationX || bLowerBoundViolationY || bLowerBoundViolationZ || bUpperBoundViolationX 00431 || bUpperBoundViolationY || bUpperBoundViolationZ || (!boundingBoxDefined_)) 00432 { 00433 00434 double octreeSideLen; 00435 unsigned char childIdx; 00436 00437 if (this->leafCount_ > 0) 00438 { 00439 // octree not empty - we add another tree level and thus increase its size by a factor of 2*2*2 00440 childIdx = ((!bUpperBoundViolationX) << 2) | ((!bUpperBoundViolationY) << 1) | ((!bUpperBoundViolationZ)); 00441 00442 OctreeBranch* newRootBranch; 00443 00444 this->createBranch (newRootBranch); 00445 this->branchCount_++; 00446 00447 this->setBranchChild (*newRootBranch, childIdx, this->rootNode_); 00448 00449 this->rootNode_ = newRootBranch; 00450 00451 octreeSideLen = (double)maxKeys_ * resolution_ ; 00452 00453 if (!bUpperBoundViolationX) 00454 minX_ -= octreeSideLen; 00455 00456 if (!bUpperBoundViolationY) 00457 minY_ -= octreeSideLen; 00458 00459 if (!bUpperBoundViolationZ) 00460 minZ_ -= octreeSideLen; 00461 00462 // configure tree depth of octree 00463 this->octreeDepth_ ++; 00464 this->setTreeDepth (this->octreeDepth_); 00465 maxKeys_ = (1 << this->octreeDepth_); 00466 00467 // recalculate bounding box width 00468 octreeSideLen = (double)maxKeys_ * resolution_ - minValue; 00469 00470 // increase octree bounding box 00471 maxX_ = minX_ + octreeSideLen; 00472 maxY_ = minY_ + octreeSideLen; 00473 maxZ_ = minZ_ + octreeSideLen; 00474 00475 } 00476 else 00477 { 00478 // octree is empty - we set the center of the bounding box to our first pixel 00479 this->minX_ = pointIdx_arg.x - this->resolution_ / 2; 00480 this->minY_ = pointIdx_arg.y - this->resolution_ / 2; 00481 this->minZ_ = pointIdx_arg.z - this->resolution_ / 2; 00482 00483 this->maxX_ = pointIdx_arg.x + this->resolution_ / 2; 00484 this->maxY_ = pointIdx_arg.y + this->resolution_ / 2; 00485 this->maxZ_ = pointIdx_arg.z + this->resolution_ / 2; 00486 00487 getKeyBitSize(); 00488 } 00489 00490 boundingBoxDefined_ = true; 00491 } 00492 else 00493 // no bound violations anymore - leave while loop 00494 break; 00495 } 00496 00497 00498 00499 } 00500 00502 template<typename PointT, typename LeafT, typename OctreeT> void 00503 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::addPointIdx (const int pointIdx_arg) 00504 { 00505 OctreeKey key; 00506 00507 assert (pointIdx_arg < (int) input_->points.size()); 00508 00509 const PointT& point = input_->points[pointIdx_arg]; 00510 00511 // make sure bounding box is big enough 00512 adoptBoundingBoxToPoint (point); 00513 00514 // generate key 00515 genOctreeKeyforPoint (point, key); 00516 00517 // add point to octree at key 00518 this->add (key, pointIdx_arg); 00519 } 00520 00522 template<typename PointT, typename LeafT, typename OctreeT> const PointT& 00523 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::getPointByIndex (const unsigned int index_arg) const 00524 { 00525 // retrieve point from input cloud 00526 assert (index_arg < (unsigned int)input_->points.size ()); 00527 return (this->input_->points[index_arg]); 00528 } 00529 00531 template<typename PointT, typename LeafT, typename OctreeT> LeafT* 00532 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::findLeafAtPoint (const PointT& point) const 00533 { 00534 OctreeKey key; 00535 00536 // generate key for point 00537 this->genOctreeKeyforPoint (point, key); 00538 00539 return (this->findLeaf (key)); 00540 } 00541 00543 template<typename PointT, typename LeafT, typename OctreeT> void 00544 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::getKeyBitSize () 00545 { 00546 unsigned int maxVoxels; 00547 00548 unsigned int maxKeyX; 00549 unsigned int maxKeyY; 00550 unsigned int maxKeyZ; 00551 00552 double octreeSideLen; 00553 00554 const float minValue = std::numeric_limits<float>::epsilon(); 00555 00556 // find maximum key values for x, y, z 00557 maxKeyX = (unsigned int)((maxX_ - minX_) / resolution_); 00558 maxKeyY = (unsigned int)((maxY_ - minY_) / resolution_); 00559 maxKeyZ = (unsigned int)((maxZ_ - minZ_) / resolution_); 00560 00561 // find maximum amount of keys 00562 maxVoxels = max (max (max (maxKeyX, maxKeyY), maxKeyZ), (unsigned int)2); 00563 00564 00565 // tree depth == amount of bits of maxVoxels 00566 this->octreeDepth_ = max ((min ((unsigned int)OCT_MAXTREEDEPTH, (unsigned int)ceil (this->Log2 (maxVoxels)-minValue))), 00567 (unsigned int)0); 00568 00569 maxKeys_ = (1 << this->octreeDepth_); 00570 00571 octreeSideLen = (double)maxKeys_ * resolution_-minValue; 00572 00573 if (this->leafCount_ == 0) 00574 { 00575 double octreeOversizeX; 00576 double octreeOversizeY; 00577 double octreeOversizeZ; 00578 00579 octreeOversizeX = (octreeSideLen - (maxX_ - minX_)) / 2.0; 00580 octreeOversizeY = (octreeSideLen - (maxY_ - minY_)) / 2.0; 00581 octreeOversizeZ = (octreeSideLen - (maxZ_ - minZ_)) / 2.0; 00582 00583 minX_ -= octreeOversizeX; 00584 minY_ -= octreeOversizeY; 00585 minZ_ -= octreeOversizeZ; 00586 00587 maxX_ += octreeOversizeX; 00588 maxY_ += octreeOversizeY; 00589 maxZ_ += octreeOversizeZ; 00590 } 00591 else 00592 { 00593 maxX_ = minX_ + octreeSideLen; 00594 maxY_ = minY_ + octreeSideLen; 00595 maxZ_ = minZ_ + octreeSideLen; 00596 } 00597 00598 // configure tree depth of octree 00599 this->setTreeDepth (this->octreeDepth_); 00600 00601 } 00602 00604 template<typename PointT, typename LeafT, typename OctreeT> void 00605 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::genOctreeKeyforPoint (const PointT& point_arg, 00606 OctreeKey & key_arg) const 00607 { 00608 // calculate integer key for point coordinates 00609 key_arg.x = min ((unsigned int)((point_arg.x - this->minX_) / this->resolution_), maxKeys_ - 1); 00610 key_arg.y = min ((unsigned int)((point_arg.y - this->minY_) / this->resolution_), maxKeys_ - 1); 00611 key_arg.z = min ((unsigned int)((point_arg.z - this->minZ_) / this->resolution_), maxKeys_ - 1); 00612 } 00613 00615 template<typename PointT, typename LeafT, typename OctreeT> void 00616 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::genOctreeKeyforPoint ( 00617 const double pointX_arg, const double pointY_arg, 00618 const double pointZ_arg, OctreeKey & key_arg) const 00619 { 00620 PointT tempPoint; 00621 00622 tempPoint.x = (float)pointX_arg; 00623 tempPoint.y = (float)pointY_arg; 00624 tempPoint.z = (float)pointZ_arg; 00625 00626 // generate key for point 00627 genOctreeKeyforPoint (tempPoint, key_arg); 00628 } 00629 00631 template<typename PointT, typename LeafT, typename OctreeT> bool 00632 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::genOctreeKeyForDataT (const int& data_arg, OctreeKey & key_arg) const 00633 { 00634 const PointT tempPoint = getPointByIndex (data_arg); 00635 00636 // generate key for point 00637 genOctreeKeyforPoint (tempPoint, key_arg); 00638 00639 return (true); 00640 } 00641 00643 template<typename PointT, typename LeafT, typename OctreeT> void 00644 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::genLeafNodeCenterFromOctreeKey (const OctreeKey & key, PointT & point) const 00645 { 00646 // define point to leaf node voxel center 00647 point.x = (float)(((double)key.x + 0.5f) * this->resolution_ + this->minX_); 00648 point.y = (float)(((double)key.y + 0.5f) * this->resolution_ + this->minY_); 00649 point.z = (float)(((double)key.z + 0.5f) * this->resolution_ + this->minZ_); 00650 } 00651 00653 template<typename PointT, typename LeafT, typename OctreeT> void 00654 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::genVoxelCenterFromOctreeKey ( 00655 const OctreeKey & key_arg, 00656 unsigned int treeDepth_arg, 00657 PointT& point_arg) const 00658 { 00659 // generate point for voxel center defined by treedepth (bitLen) and key 00660 point_arg.x = (float)(((double)(key_arg.x) + 0.5f) * (this->resolution_ * (double)(1 << (this->octreeDepth_ 00661 - treeDepth_arg))) + this->minX_); 00662 point_arg.y = (float)(((double)(key_arg.y) + 0.5f) * (this->resolution_ * (double)(1 << (this->octreeDepth_ 00663 - treeDepth_arg))) + this->minY_); 00664 point_arg.z = (float)(((double)(key_arg.z) + 0.5f) * (this->resolution_ * (double)(1 << (this->octreeDepth_ 00665 - treeDepth_arg))) + this->minZ_); 00666 } 00667 00669 template<typename PointT, typename LeafT, typename OctreeT> void 00670 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::genVoxelBoundsFromOctreeKey ( 00671 const OctreeKey & key_arg, 00672 unsigned int treeDepth_arg, 00673 Eigen::Vector3f &min_pt, 00674 Eigen::Vector3f &max_pt) const 00675 { 00676 // calculate voxel size of current tree depth 00677 double voxel_side_len = this->resolution_ * (double)(1 << (this->octreeDepth_ - treeDepth_arg)); 00678 00679 // calculate voxel bounds 00680 min_pt (0) = (float)((double)(key_arg.x) * voxel_side_len + this->minX_); 00681 min_pt (1) = (float)((double)(key_arg.y) * voxel_side_len + this->minY_); 00682 min_pt (2) = (float)((double)(key_arg.z) * voxel_side_len + this->minZ_); 00683 00684 max_pt (0) = (float)((double)(key_arg.x + 1) * voxel_side_len + this->minX_); 00685 max_pt (1) = (float)((double)(key_arg.y + 1) * voxel_side_len + this->minY_); 00686 max_pt (2) = (float)((double)(key_arg.z + 1) * voxel_side_len + this->minZ_); 00687 } 00688 00690 template<typename PointT, typename LeafT, typename OctreeT> double 00691 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::getVoxelSquaredSideLen (unsigned int treeDepth_arg) const 00692 { 00693 double sideLen; 00694 00695 // side length of the voxel cube increases exponentially with the octree depth 00696 sideLen = this->resolution_ * (double)(1 << (this->octreeDepth_ - treeDepth_arg)); 00697 00698 // squared voxel side length 00699 sideLen *= sideLen; 00700 00701 return (sideLen); 00702 } 00703 00705 template<typename PointT, typename LeafT, typename OctreeT> double 00706 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::getVoxelSquaredDiameter (unsigned int treeDepth_arg) const 00707 { 00708 // return the squared side length of the voxel cube as a function of the octree depth 00709 return (getVoxelSquaredSideLen (treeDepth_arg) * 3); 00710 } 00711 00713 template<typename PointT, typename LeafT, typename OctreeT> int 00714 pcl::octree::OctreePointCloud<PointT, LeafT, OctreeT>::getOccupiedVoxelCentersRecursive ( 00715 const OctreeBranch* node_arg, 00716 const OctreeKey& key_arg, 00717 std::vector<PointT, 00718 Eigen::aligned_allocator<PointT> > &voxelCenterList_arg) const 00719 { 00720 // child iterator 00721 unsigned char childIdx; 00722 00723 int voxelCount = 0; 00724 00725 // iterate over all children 00726 for (childIdx = 0; childIdx < 8; childIdx++) 00727 { 00728 if (!this->branchHasChild (*node_arg, childIdx)) 00729 continue; 00730 00731 const OctreeNode * childNode; 00732 childNode = this->getBranchChild (*node_arg, childIdx); 00733 00734 // generate new key for current branch voxel 00735 OctreeKey newKey; 00736 newKey.x = (key_arg.x << 1) | (!!(childIdx & (1 << 2))); 00737 newKey.y = (key_arg.y << 1) | (!!(childIdx & (1 << 1))); 00738 newKey.z = (key_arg.z << 1) | (!!(childIdx & (1 << 0))); 00739 00740 switch (childNode->getNodeType ()) 00741 { 00742 case BRANCH_NODE: 00743 { 00744 // recursively proceed with indexed child branch 00745 voxelCount += getOccupiedVoxelCentersRecursive ((OctreeBranch*)childNode, newKey, voxelCenterList_arg); 00746 break; 00747 } 00748 case LEAF_NODE: 00749 { 00750 PointT newPoint; 00751 00752 genLeafNodeCenterFromOctreeKey (newKey, newPoint); 00753 voxelCenterList_arg.push_back (newPoint); 00754 00755 voxelCount++; 00756 break; 00757 } 00758 default: 00759 break; 00760 } 00761 } 00762 return (voxelCount); 00763 } 00764 00765 #define PCL_INSTANTIATE_OctreePointCloudSingleBufferWithLeafDataTVector(T) template class PCL_EXPORTS pcl::octree::OctreePointCloud<T, pcl::octree::OctreeLeafDataTVector<int> , pcl::octree::OctreeBase<int, pcl::octree::OctreeLeafDataTVector<int> > >; 00766 #define PCL_INSTANTIATE_OctreePointCloudDoubleBufferWithLeafDataTVector(T) template class PCL_EXPORTS pcl::octree::OctreePointCloud<T, pcl::octree::OctreeLeafDataTVector<int> , pcl::octree::Octree2BufBase<int, pcl::octree::OctreeLeafDataTVector<int> > >; 00767 #define PCL_INSTANTIATE_OctreePointCloudLowMemWithLeafDataTVector(T) template class PCL_EXPORTS pcl::octree::OctreePointCloud<T, pcl::octree::OctreeLeafDataTVector<int> , pcl::octree::OctreeLowMemBase<int, pcl::octree::OctreeLeafDataTVector<int> > >; 00768 00769 #define PCL_INSTANTIATE_OctreePointCloudSingleBufferWithLeafDataT(T) template class PCL_EXPORTS pcl::octree::OctreePointCloud<T, pcl::octree::OctreeLeafDataT<int> , pcl::octree::OctreeBase<int, pcl::octree::OctreeLeafDataT<int> > >; 00770 #define PCL_INSTANTIATE_OctreePointCloudDoubleBufferWithLeafDataT(T) template class PCL_EXPORTS pcl::octree::OctreePointCloud<T, pcl::octree::OctreeLeafDataT<int> , pcl::octree::Octree2BufBase<int, pcl::octree::OctreeLeafDataT<int> > >; 00771 #define PCL_INSTANTIATE_OctreePointCloudLowMemWithLeafDataT(T) template class PCL_EXPORTS pcl::octree::OctreePointCloud<T, pcl::octree::OctreeLeafDataT<int> , pcl::octree::OctreeLowMemBase<int, pcl::octree::OctreeLeafDataT<int> > >; 00772 00773 #define PCL_INSTANTIATE_OctreePointCloudSingleBufferWithEmptyLeaf(T) template class PCL_EXPORTS pcl::octree::OctreePointCloud<T, pcl::octree::OctreeLeafEmpty<int> , pcl::octree::OctreeBase<int, pcl::octree::OctreeLeafEmpty<int> > >; 00774 #define PCL_INSTANTIATE_OctreePointCloudDoubleBufferWithEmptyLeaf(T) template class PCL_EXPORTS pcl::octree::OctreePointCloud<T, pcl::octree::OctreeLeafEmpty<int> , pcl::octree::Octree2BufBase<int, pcl::octree::OctreeLeafEmpty<int> > >; 00775 #define PCL_INSTANTIATE_OctreePointCloudLowMemWithEmptyLeaf(T) template class PCL_EXPORTS pcl::octree::OctreePointCloud<T, pcl::octree::OctreeLeafEmpty<int> , pcl::octree::OctreeLowMemBase<int, pcl::octree::OctreeLeafEmpty<int> > >; 00776 00777 #endif /* OCTREE_POINTCLOUD_HPP_ */
1.8.0