42 #include <pcl/common/point_tests.h>
43 #include <pcl/octree/impl/octree_base.hpp>
49 typename LeafContainerT,
50 typename BranchContainerT,
58 , resolution_(resolution)
65 , bounding_box_defined_(false)
66 , max_objs_per_leaf_(0)
68 assert(resolution > 0.0f);
73 typename LeafContainerT,
74 typename BranchContainerT,
81 for (
const int& index : *indices_) {
82 assert((index >= 0) && (index <
static_cast<int>(input_->size())));
86 this->addPointIdx(index);
91 for (std::size_t i = 0; i < input_->size(); i++) {
94 this->addPointIdx(
static_cast<unsigned int>(i));
101 template <
typename PointT,
102 typename LeafContainerT,
103 typename BranchContainerT,
109 this->addPointIdx(point_idx_arg);
111 indices_arg->push_back(point_idx_arg);
115 template <
typename PointT,
116 typename LeafContainerT,
117 typename BranchContainerT,
123 assert(cloud_arg == input_);
125 cloud_arg->push_back(point_arg);
127 this->addPointIdx(
static_cast<const int>(cloud_arg->size()) - 1);
131 template <
typename PointT,
132 typename LeafContainerT,
133 typename BranchContainerT,
141 assert(cloud_arg == input_);
142 assert(indices_arg == indices_);
144 cloud_arg->push_back(point_arg);
146 this->addPointFromCloud(
static_cast<const int>(cloud_arg->size()) - 1, indices_arg);
150 template <
typename PointT,
151 typename LeafContainerT,
152 typename BranchContainerT,
158 if (!isPointWithinBoundingBox(point_arg)) {
165 this->genOctreeKeyforPoint(point_arg, key);
168 return (this->existLeaf(key));
172 template <
typename PointT,
173 typename LeafContainerT,
174 typename BranchContainerT,
181 const PointT& point = (*this->input_)[point_idx_arg];
184 return (this->isVoxelOccupiedAtPoint(point));
188 template <
typename PointT,
189 typename LeafContainerT,
190 typename BranchContainerT,
195 const double point_y_arg,
196 const double point_z_arg)
const
200 point.x = point_x_arg;
201 point.y = point_y_arg;
202 point.z = point_z_arg;
205 return (this->isVoxelOccupiedAtPoint(point));
209 template <
typename PointT,
210 typename LeafContainerT,
211 typename BranchContainerT,
217 if (!isPointWithinBoundingBox(point_arg)) {
224 this->genOctreeKeyforPoint(point_arg, key);
226 this->removeLeaf(key);
230 template <
typename PointT,
231 typename LeafContainerT,
232 typename BranchContainerT,
239 const PointT& point = (*this->input_)[point_idx_arg];
242 this->deleteVoxelAtPoint(point);
246 template <
typename PointT,
247 typename LeafContainerT,
248 typename BranchContainerT,
255 key.
x = key.
y = key.
z = 0;
257 voxel_center_list_arg.clear();
259 return getOccupiedVoxelCentersRecursive(this->root_node_, key, voxel_center_list_arg);
263 template <
typename PointT,
264 typename LeafContainerT,
265 typename BranchContainerT,
270 const Eigen::Vector3f& end,
274 Eigen::Vector3f direction = end - origin;
275 float norm = direction.norm();
276 direction.normalize();
278 const float step_size =
static_cast<float>(resolution_) * precision;
280 const int nsteps = std::max(1,
static_cast<int>(norm / step_size));
284 bool bkeyDefined =
false;
287 for (
int i = 0; i < nsteps; ++i) {
288 Eigen::Vector3f p = origin + (direction * step_size *
static_cast<float>(i));
296 this->genOctreeKeyforPoint(octree_p, key);
299 if ((key == prev_key) && (bkeyDefined))
306 genLeafNodeCenterFromOctreeKey(key, center);
307 voxel_center_list.push_back(center);
315 this->genOctreeKeyforPoint(end_p, end_key);
316 if (!(end_key == prev_key)) {
318 genLeafNodeCenterFromOctreeKey(end_key, center);
319 voxel_center_list.push_back(center);
322 return (
static_cast<int>(voxel_center_list.size()));
326 template <
typename PointT,
327 typename LeafContainerT,
328 typename BranchContainerT,
335 double minX, minY, minZ, maxX, maxY, maxZ;
341 assert(this->leaf_count_ == 0);
345 float minValue = std::numeric_limits<float>::epsilon() * 512.0f;
351 maxX = max_pt.x + minValue;
352 maxY = max_pt.y + minValue;
353 maxZ = max_pt.z + minValue;
356 defineBoundingBox(minX, minY, minZ, maxX, maxY, maxZ);
360 template <
typename PointT,
361 typename LeafContainerT,
362 typename BranchContainerT,
367 const double min_y_arg,
368 const double min_z_arg,
369 const double max_x_arg,
370 const double max_y_arg,
371 const double max_z_arg)
374 assert(this->leaf_count_ == 0);
376 assert(max_x_arg >= min_x_arg);
377 assert(max_y_arg >= min_y_arg);
378 assert(max_z_arg >= min_z_arg);
389 min_x_ = std::min(min_x_, max_x_);
390 min_y_ = std::min(min_y_, max_y_);
391 min_z_ = std::min(min_z_, max_z_);
393 max_x_ = std::max(min_x_, max_x_);
394 max_y_ = std::max(min_y_, max_y_);
395 max_z_ = std::max(min_z_, max_z_);
400 bounding_box_defined_ =
true;
404 template <
typename PointT,
405 typename LeafContainerT,
406 typename BranchContainerT,
411 const double max_y_arg,
412 const double max_z_arg)
415 assert(this->leaf_count_ == 0);
417 assert(max_x_arg >= 0.0f);
418 assert(max_y_arg >= 0.0f);
419 assert(max_z_arg >= 0.0f);
430 min_x_ = std::min(min_x_, max_x_);
431 min_y_ = std::min(min_y_, max_y_);
432 min_z_ = std::min(min_z_, max_z_);
434 max_x_ = std::max(min_x_, max_x_);
435 max_y_ = std::max(min_y_, max_y_);
436 max_z_ = std::max(min_z_, max_z_);
441 bounding_box_defined_ =
true;
445 template <
typename PointT,
446 typename LeafContainerT,
447 typename BranchContainerT,
454 assert(this->leaf_count_ == 0);
456 assert(cubeLen_arg >= 0.0f);
459 max_x_ = cubeLen_arg;
462 max_y_ = cubeLen_arg;
465 max_z_ = cubeLen_arg;
467 min_x_ = std::min(min_x_, max_x_);
468 min_y_ = std::min(min_y_, max_y_);
469 min_z_ = std::min(min_z_, max_z_);
471 max_x_ = std::max(min_x_, max_x_);
472 max_y_ = std::max(min_y_, max_y_);
473 max_z_ = std::max(min_z_, max_z_);
478 bounding_box_defined_ =
true;
482 template <
typename PointT,
483 typename LeafContainerT,
484 typename BranchContainerT,
493 double& max_z_arg)
const
505 template <
typename PointT,
506 typename LeafContainerT,
507 typename BranchContainerT,
514 const float minValue = std::numeric_limits<float>::epsilon();
518 bool bLowerBoundViolationX = (point_idx_arg.x < min_x_);
519 bool bLowerBoundViolationY = (point_idx_arg.y < min_y_);
520 bool bLowerBoundViolationZ = (point_idx_arg.z < min_z_);
522 bool bUpperBoundViolationX = (point_idx_arg.x >= max_x_);
523 bool bUpperBoundViolationY = (point_idx_arg.y >= max_y_);
524 bool bUpperBoundViolationZ = (point_idx_arg.z >= max_z_);
527 if (bLowerBoundViolationX || bLowerBoundViolationY || bLowerBoundViolationZ ||
528 bUpperBoundViolationX || bUpperBoundViolationY || bUpperBoundViolationZ ||
529 (!bounding_box_defined_)) {
531 if (bounding_box_defined_) {
533 double octreeSideLen;
534 unsigned char child_idx;
538 child_idx =
static_cast<unsigned char>(((!bUpperBoundViolationX) << 2) |
539 ((!bUpperBoundViolationY) << 1) |
540 ((!bUpperBoundViolationZ)));
545 this->branch_count_++;
547 this->setBranchChildPtr(*newRootBranch, child_idx, this->root_node_);
549 this->root_node_ = newRootBranch;
551 octreeSideLen =
static_cast<double>(1 << this->octree_depth_) * resolution_;
553 if (!bUpperBoundViolationX)
554 min_x_ -= octreeSideLen;
556 if (!bUpperBoundViolationY)
557 min_y_ -= octreeSideLen;
559 if (!bUpperBoundViolationZ)
560 min_z_ -= octreeSideLen;
563 this->octree_depth_++;
564 this->setTreeDepth(this->octree_depth_);
568 static_cast<double>(1 << this->octree_depth_) * resolution_ - minValue;
571 max_x_ = min_x_ + octreeSideLen;
572 max_y_ = min_y_ + octreeSideLen;
573 max_z_ = min_z_ + octreeSideLen;
578 this->min_x_ = point_idx_arg.x - this->resolution_ / 2;
579 this->min_y_ = point_idx_arg.y - this->resolution_ / 2;
580 this->min_z_ = point_idx_arg.z - this->resolution_ / 2;
582 this->max_x_ = point_idx_arg.x + this->resolution_ / 2;
583 this->max_y_ = point_idx_arg.y + this->resolution_ / 2;
584 this->max_z_ = point_idx_arg.z + this->resolution_ / 2;
588 bounding_box_defined_ =
true;
598 template <
typename PointT,
599 typename LeafContainerT,
600 typename BranchContainerT,
606 unsigned char child_idx,
607 unsigned int depth_mask)
612 std::size_t leaf_obj_count = (*leaf_node)->getSize();
615 std::vector<int> leafIndices;
616 leafIndices.reserve(leaf_obj_count);
618 (*leaf_node)->getPointIndices(leafIndices);
621 this->deleteBranchChild(*parent_branch, child_idx);
625 BranchNode* childBranch = this->createBranchChild(*parent_branch, child_idx);
626 this->branch_count_++;
631 for (
const int& leafIndex : leafIndices) {
633 const PointT& point_from_index = (*input_)[leafIndex];
635 genOctreeKeyforPoint(point_from_index, new_index_key);
639 this->createLeafRecursive(
640 new_index_key, depth_mask, childBranch, newLeaf, newBranchParent);
642 (*newLeaf)->addPointIndex(leafIndex);
648 template <
typename PointT,
649 typename LeafContainerT,
650 typename BranchContainerT,
658 assert(point_idx_arg <
static_cast<int>(input_->size()));
660 const PointT& point = (*input_)[point_idx_arg];
663 adoptBoundingBoxToPoint(point);
666 genOctreeKeyforPoint(point, key);
670 unsigned int depth_mask = this->createLeafRecursive(
671 key, this->depth_mask_, this->root_node_, leaf_node, parent_branch_of_leaf_node);
673 if (this->dynamic_depth_enabled_ && depth_mask) {
675 std::size_t leaf_obj_count = (*leaf_node)->getSize();
677 while (leaf_obj_count >= max_objs_per_leaf_ && depth_mask) {
681 expandLeafNode(leaf_node, parent_branch_of_leaf_node, child_idx, depth_mask);
683 depth_mask = this->createLeafRecursive(key,
687 parent_branch_of_leaf_node);
688 leaf_obj_count = (*leaf_node)->getSize();
692 (*leaf_node)->addPointIndex(point_idx_arg);
696 template <
typename PointT,
697 typename LeafContainerT,
698 typename BranchContainerT,
705 assert(index_arg <
static_cast<unsigned int>(input_->size()));
706 return ((*this->input_)[index_arg]);
710 template <
typename PointT,
711 typename LeafContainerT,
712 typename BranchContainerT,
718 unsigned int max_voxels;
720 unsigned int max_key_x;
721 unsigned int max_key_y;
722 unsigned int max_key_z;
724 double octree_side_len;
726 const float minValue = std::numeric_limits<float>::epsilon();
730 static_cast<unsigned int>(std::ceil((max_x_ - min_x_ - minValue) / resolution_));
732 static_cast<unsigned int>(std::ceil((max_y_ - min_y_ - minValue) / resolution_));
734 static_cast<unsigned int>(std::ceil((max_z_ - min_z_ - minValue) / resolution_));
737 max_voxels = std::max(std::max(std::max(max_key_x, max_key_y), max_key_z),
738 static_cast<unsigned int>(2));
741 this->octree_depth_ =
742 std::max((std::min(
static_cast<unsigned int>(OctreeKey::maxDepth),
743 static_cast<unsigned int>(
744 std::ceil(std::log2(max_voxels) - minValue)))),
745 static_cast<unsigned int>(0));
747 octree_side_len =
static_cast<double>(1 << this->octree_depth_) * resolution_;
749 if (this->leaf_count_ == 0) {
750 double octree_oversize_x;
751 double octree_oversize_y;
752 double octree_oversize_z;
754 octree_oversize_x = (octree_side_len - (max_x_ - min_x_)) / 2.0;
755 octree_oversize_y = (octree_side_len - (max_y_ - min_y_)) / 2.0;
756 octree_oversize_z = (octree_side_len - (max_z_ - min_z_)) / 2.0;
758 assert(octree_oversize_x > -minValue);
759 assert(octree_oversize_y > -minValue);
760 assert(octree_oversize_z > -minValue);
762 if (octree_oversize_x > minValue) {
763 min_x_ -= octree_oversize_x;
764 max_x_ += octree_oversize_x;
766 if (octree_oversize_y > minValue) {
767 min_y_ -= octree_oversize_y;
768 max_y_ += octree_oversize_y;
770 if (octree_oversize_z > minValue) {
771 min_z_ -= octree_oversize_z;
772 max_z_ += octree_oversize_z;
776 max_x_ = min_x_ + octree_side_len;
777 max_y_ = min_y_ + octree_side_len;
778 max_z_ = min_z_ + octree_side_len;
782 this->setTreeDepth(this->octree_depth_);
786 template <
typename PointT,
787 typename LeafContainerT,
788 typename BranchContainerT,
796 static_cast<unsigned int>((point_arg.x - this->min_x_) / this->resolution_);
798 static_cast<unsigned int>((point_arg.y - this->min_y_) / this->resolution_);
800 static_cast<unsigned int>((point_arg.z - this->min_z_) / this->resolution_);
802 assert(key_arg.
x <= this->max_key_.x);
803 assert(key_arg.
y <= this->max_key_.y);
804 assert(key_arg.
z <= this->max_key_.z);
808 template <
typename PointT,
809 typename LeafContainerT,
810 typename BranchContainerT,
815 const double point_y_arg,
816 const double point_z_arg,
821 temp_point.x =
static_cast<float>(point_x_arg);
822 temp_point.y =
static_cast<float>(point_y_arg);
823 temp_point.z =
static_cast<float>(point_z_arg);
826 genOctreeKeyforPoint(temp_point, key_arg);
830 template <
typename PointT,
831 typename LeafContainerT,
832 typename BranchContainerT,
838 const PointT temp_point = getPointByIndex(data_arg);
841 genOctreeKeyforPoint(temp_point, key_arg);
847 template <
typename PointT,
848 typename LeafContainerT,
849 typename BranchContainerT,
856 point.x =
static_cast<float>((
static_cast<double>(key.
x) + 0.5f) * this->resolution_ +
858 point.y =
static_cast<float>((
static_cast<double>(key.
y) + 0.5f) * this->resolution_ +
860 point.z =
static_cast<float>((
static_cast<double>(key.
z) + 0.5f) * this->resolution_ +
865 template <
typename PointT,
866 typename LeafContainerT,
867 typename BranchContainerT,
872 unsigned int tree_depth_arg,
876 point_arg.x =
static_cast<float>(
877 (
static_cast<double>(key_arg.
x) + 0.5f) *
879 static_cast<double>(1 << (this->octree_depth_ - tree_depth_arg))) +
881 point_arg.y =
static_cast<float>(
882 (
static_cast<double>(key_arg.
y) + 0.5f) *
884 static_cast<double>(1 << (this->octree_depth_ - tree_depth_arg))) +
886 point_arg.z =
static_cast<float>(
887 (
static_cast<double>(key_arg.
z) + 0.5f) *
889 static_cast<double>(1 << (this->octree_depth_ - tree_depth_arg))) +
894 template <
typename PointT,
895 typename LeafContainerT,
896 typename BranchContainerT,
901 unsigned int tree_depth_arg,
902 Eigen::Vector3f& min_pt,
903 Eigen::Vector3f& max_pt)
const
906 double voxel_side_len =
908 static_cast<double>(1 << (this->octree_depth_ - tree_depth_arg));
911 min_pt(0) =
static_cast<float>(
static_cast<double>(key_arg.
x) * voxel_side_len +
913 min_pt(1) =
static_cast<float>(
static_cast<double>(key_arg.
y) * voxel_side_len +
915 min_pt(2) =
static_cast<float>(
static_cast<double>(key_arg.
z) * voxel_side_len +
918 max_pt(0) =
static_cast<float>(
static_cast<double>(key_arg.
x + 1) * voxel_side_len +
920 max_pt(1) =
static_cast<float>(
static_cast<double>(key_arg.
y + 1) * voxel_side_len +
922 max_pt(2) =
static_cast<float>(
static_cast<double>(key_arg.
z + 1) * voxel_side_len +
927 template <
typename PointT,
928 typename LeafContainerT,
929 typename BranchContainerT,
938 side_len = this->resolution_ *
939 static_cast<double>(1 << (this->octree_depth_ - tree_depth_arg));
942 side_len *= side_len;
948 template <
typename PointT,
949 typename LeafContainerT,
950 typename BranchContainerT,
957 return (getVoxelSquaredSideLen(tree_depth_arg) * 3);
961 template <
typename PointT,
962 typename LeafContainerT,
963 typename BranchContainerT,
974 for (
unsigned char child_idx = 0; child_idx < 8; child_idx++) {
975 if (!this->branchHasChild(*node_arg, child_idx))
979 child_node = this->getBranchChildPtr(*node_arg, child_idx);
983 new_key.
x = (key_arg.
x << 1) | (!!(child_idx & (1 << 2)));
984 new_key.
y = (key_arg.
y << 1) | (!!(child_idx & (1 << 1)));
985 new_key.
z = (key_arg.
z << 1) | (!!(child_idx & (1 << 0)));
990 voxel_count += getOccupiedVoxelCentersRecursive(
991 static_cast<const BranchNode*
>(child_node), new_key, voxel_center_list_arg);
997 genLeafNodeCenterFromOctreeKey(new_key, new_point);
998 voxel_center_list_arg.push_back(new_point);
1007 return (voxel_count);
1010 #define PCL_INSTANTIATE_OctreePointCloudSingleBufferWithLeafDataTVector(T) \
1011 template class PCL_EXPORTS pcl::octree::OctreePointCloud< \
1013 pcl::octree::OctreeContainerPointIndices, \
1014 pcl::octree::OctreeContainerEmpty, \
1015 pcl::octree::OctreeBase<pcl::octree::OctreeContainerPointIndices, \
1016 pcl::octree::OctreeContainerEmpty>>;
1017 #define PCL_INSTANTIATE_OctreePointCloudDoubleBufferWithLeafDataTVector(T) \
1018 template class PCL_EXPORTS pcl::octree::OctreePointCloud< \
1020 pcl::octree::OctreeContainerPointIndices, \
1021 pcl::octree::OctreeContainerEmpty, \
1022 pcl::octree::Octree2BufBase<pcl::octree::OctreeContainerPointIndices, \
1023 pcl::octree::OctreeContainerEmpty>>;
1025 #define PCL_INSTANTIATE_OctreePointCloudSingleBufferWithLeafDataT(T) \
1026 template class PCL_EXPORTS pcl::octree::OctreePointCloud< \
1028 pcl::octree::OctreeContainerPointIndex, \
1029 pcl::octree::OctreeContainerEmpty, \
1030 pcl::octree::OctreeBase<pcl::octree::OctreeContainerPointIndex, \
1031 pcl::octree::OctreeContainerEmpty>>;
1032 #define PCL_INSTANTIATE_OctreePointCloudDoubleBufferWithLeafDataT(T) \
1033 template class PCL_EXPORTS pcl::octree::OctreePointCloud< \
1035 pcl::octree::OctreeContainerPointIndex, \
1036 pcl::octree::OctreeContainerEmpty, \
1037 pcl::octree::Octree2BufBase<pcl::octree::OctreeContainerPointIndex, \
1038 pcl::octree::OctreeContainerEmpty>>;
1040 #define PCL_INSTANTIATE_OctreePointCloudSingleBufferWithEmptyLeaf(T) \
1041 template class PCL_EXPORTS pcl::octree::OctreePointCloud< \
1043 pcl::octree::OctreeContainerEmpty, \
1044 pcl::octree::OctreeContainerEmpty, \
1045 pcl::octree::OctreeBase<pcl::octree::OctreeContainerEmpty, \
1046 pcl::octree::OctreeContainerEmpty>>;
1047 #define PCL_INSTANTIATE_OctreePointCloudDoubleBufferWithEmptyLeaf(T) \
1048 template class PCL_EXPORTS pcl::octree::OctreePointCloud< \
1050 pcl::octree::OctreeContainerEmpty, \
1051 pcl::octree::OctreeContainerEmpty, \
1052 pcl::octree::Octree2BufBase<pcl::octree::OctreeContainerEmpty, \
1053 pcl::octree::OctreeContainerEmpty>>;