602 PCL_WARN (
"[pcl::%s::applyFilter] No input dataset given!\n", getClassName ().c_str ());
603 output.width = output.height = 0;
610 output.is_dense =
true;
612 Eigen::Vector4f min_p, max_p;
614 if (!filter_field_name_.empty ())
615 getMinMax3D<PointT> (input_, *indices_, filter_field_name_,
static_cast<float> (filter_limit_min_),
static_cast<float> (filter_limit_max_), min_p, max_p, filter_limit_negative_);
617 getMinMax3D<PointT> (*input_, *indices_, min_p, max_p);
620 std::int64_t dx =
static_cast<std::int64_t
>((max_p[0] - min_p[0]) * inverse_leaf_size_[0])+1;
621 std::int64_t dy =
static_cast<std::int64_t
>((max_p[1] - min_p[1]) * inverse_leaf_size_[1])+1;
622 std::int64_t dz =
static_cast<std::int64_t
>((max_p[2] - min_p[2]) * inverse_leaf_size_[2])+1;
624 if ((dx*dy*dz) >
static_cast<std::int64_t
>(std::numeric_limits<std::int32_t>::max()))
626 PCL_WARN(
"[pcl::%s::applyFilter] Leaf size is too small for the input dataset. Integer indices would overflow.\n", getClassName().c_str());
632 min_b_[0] =
static_cast<int> (std::floor (min_p[0] * inverse_leaf_size_[0]));
633 max_b_[0] =
static_cast<int> (std::floor (max_p[0] * inverse_leaf_size_[0]));
634 min_b_[1] =
static_cast<int> (std::floor (min_p[1] * inverse_leaf_size_[1]));
635 max_b_[1] =
static_cast<int> (std::floor (max_p[1] * inverse_leaf_size_[1]));
636 min_b_[2] =
static_cast<int> (std::floor (min_p[2] * inverse_leaf_size_[2]));
637 max_b_[2] =
static_cast<int> (std::floor (max_p[2] * inverse_leaf_size_[2]));
640 div_b_ = max_b_ - min_b_ + Eigen::Vector4i::Ones ();
644 divb_mul_ = Eigen::Vector4i (1, div_b_[0], div_b_[0] * div_b_[1], 0);
647 std::vector<internal::cloud_point_index_idx> index_vector;
648 index_vector.reserve (indices_->size ());
651 if (!filter_field_name_.empty ())
654 std::vector<pcl::PCLPointField> fields;
655 int distance_idx = pcl::getFieldIndex<PointT> (filter_field_name_, fields);
656 if (distance_idx == -1) {
657 PCL_ERROR (
"[pcl::%s::applyFilter] Invalid filter field name (%s).\n", getClassName ().c_str (), filter_field_name_.c_str());
660 const auto field_offset = fields[distance_idx].offset;
665 for (
const auto& index : (*indices_))
667 if (!input_->is_dense)
673 const auto* pt_data =
reinterpret_cast<const std::uint8_t*
> (&(*input_)[index]);
674 float distance_value = 0;
675 memcpy (&distance_value, pt_data + field_offset,
sizeof (
float));
677 if (filter_limit_negative_)
680 if ((distance_value < filter_limit_max_) && (distance_value > filter_limit_min_))
686 if ((distance_value > filter_limit_max_) || (distance_value < filter_limit_min_))
690 int ijk0 =
static_cast<int> (std::floor ((*input_)[index].x * inverse_leaf_size_[0]) -
static_cast<float> (min_b_[0]));
691 int ijk1 =
static_cast<int> (std::floor ((*input_)[index].y * inverse_leaf_size_[1]) -
static_cast<float> (min_b_[1]));
692 int ijk2 =
static_cast<int> (std::floor ((*input_)[index].z * inverse_leaf_size_[2]) -
static_cast<float> (min_b_[2]));
695 int idx = ijk0 * divb_mul_[0] + ijk1 * divb_mul_[1] + ijk2 * divb_mul_[2];
696 index_vector.emplace_back(
static_cast<unsigned int> (idx), index);
705 for (
const auto& index : (*indices_))
707 if (!input_->is_dense)
712 int ijk0 =
static_cast<int> (std::floor ((*input_)[index].x * inverse_leaf_size_[0]) -
static_cast<float> (min_b_[0]));
713 int ijk1 =
static_cast<int> (std::floor ((*input_)[index].y * inverse_leaf_size_[1]) -
static_cast<float> (min_b_[1]));
714 int ijk2 =
static_cast<int> (std::floor ((*input_)[index].z * inverse_leaf_size_[2]) -
static_cast<float> (min_b_[2]));
717 int idx = ijk0 * divb_mul_[0] + ijk1 * divb_mul_[1] + ijk2 * divb_mul_[2];
718 index_vector.emplace_back(
static_cast<unsigned int> (idx), index);
725 boost::sort::spreadsort::integer_sort(index_vector.begin(), index_vector.end(), rightshift_func);
729 unsigned int total = 0;
730 unsigned int index = 0;
734 std::vector<std::pair<unsigned int, unsigned int> > first_and_last_indices_vector;
736 first_and_last_indices_vector.reserve (index_vector.size ());
737 while (index < index_vector.size ())
739 unsigned int i = index + 1;
740 while (i < index_vector.size () && index_vector[i].idx == index_vector[index].idx)
742 if (i - index >= min_points_per_voxel_)
745 first_and_last_indices_vector.emplace_back(index, i);
751 output.resize (total);
752 if (save_leaf_layout_)
757 std::uint32_t new_layout_size = div_b_[0]*div_b_[1]*div_b_[2];
759 std::uint32_t reinit_size = std::min (
static_cast<unsigned int> (new_layout_size),
static_cast<unsigned int> (leaf_layout_.size()));
760 for (std::uint32_t i = 0; i < reinit_size; i++)
762 leaf_layout_[i] = -1;
764 leaf_layout_.resize (new_layout_size, -1);
766 catch (std::bad_alloc&)
768 throw PCLException(
"VoxelGrid bin size is too low; impossible to allocate memory for layout",
769 "voxel_grid.hpp",
"applyFilter");
771 catch (std::length_error&)
773 throw PCLException(
"VoxelGrid bin size is too low; impossible to allocate memory for layout",
774 "voxel_grid.hpp",
"applyFilter");
779 for (
const auto &cp : first_and_last_indices_vector)
782 unsigned int first_index = cp.first;
783 unsigned int last_index = cp.second;
786 if (save_leaf_layout_)
787 leaf_layout_[index_vector[first_index].idx] = index;
790 if (!downsample_all_data_)
792 Eigen::Vector4f centroid (Eigen::Vector4f::Zero ());
794 for (
unsigned int li = first_index; li < last_index; ++li)
795 centroid += (*input_)[index_vector[li].cloud_point_index].getVector4fMap ();
797 centroid /=
static_cast<float> (last_index - first_index);
798 output[index].getVector4fMap () = centroid;
802 CentroidPoint<PointT> centroid;
805 for (
unsigned int li = first_index; li < last_index; ++li)
806 centroid.add ((*input_)[index_vector[li].cloud_point_index]);
808 centroid.get (output[index]);
813 output.width = output.size ();