25 template <
typename InputPo
intCloud,
typename OutputPo
intCloud = InputPo
intCloud>
28 return std::make_shared<OutputPointCloud>();
31 const double inv_leaf_size = 1.0 / leaf_size;
33 constexpr std::uint64_t invalid_coord = std::numeric_limits<std::uint64_t>::max();
34 constexpr
int coord_bit_size = 21;
35 constexpr
size_t coord_bit_mask = (1 << 21) - 1;
36 constexpr
int coord_offset = 1 << (coord_bit_size - 1);
38 std::vector<std::pair<std::uint64_t, size_t>> coord_pt(
traits::size(points));
39 tbb::parallel_for(tbb::blocked_range<size_t>(0,
traits::size(points), 64), [&](
const tbb::blocked_range<size_t>& range) {
40 for (
size_t i = range.begin(); i != range.end(); i++) {
41 const Eigen::Array4i coord = fast_floor(traits::point(points, i) * inv_leaf_size) + coord_offset;
42 if ((coord < 0).any() || (coord > coord_bit_mask).any()) {
43 std::cerr <<
"warning: voxel coord is out of range!!" << std::endl;
44 coord_pt[i] = {invalid_coord, i};
49 const std::uint64_t bits =
50 (
static_cast<std::uint64_t
>(coord[0] & coord_bit_mask) << (coord_bit_size * 0)) |
51 (
static_cast<std::uint64_t
>(coord[1] & coord_bit_mask) << (coord_bit_size * 1)) |
52 (
static_cast<std::uint64_t
>(coord[2] & coord_bit_mask) << (coord_bit_size * 2));
53 coord_pt[i] = {bits, i};
58 tbb::parallel_sort(coord_pt, [](
const auto& lhs,
const auto& rhs) {
return lhs.first < rhs.first; });
60 auto downsampled = std::make_shared<OutputPointCloud>();
64 const int block_size = 2048;
65 std::atomic_uint64_t num_points = 0;
66 tbb::parallel_for(tbb::blocked_range<size_t>(0,
traits::size(points), block_size), [&](
const tbb::blocked_range<size_t>& range) {
67 std::vector<Eigen::Vector4d> sub_points;
68 sub_points.reserve(block_size);
70 Eigen::Vector4d sum_pt =
traits::point(points, coord_pt[range.begin()].second);
71 for (
size_t i = range.begin() + 1; i != range.end(); i++) {
72 if (coord_pt[i].first == invalid_coord) {
76 if (coord_pt[i - 1].first != coord_pt[i].first) {
77 sub_points.emplace_back(sum_pt / sum_pt.w());
82 sub_points.emplace_back(sum_pt / sum_pt.w());
84 const size_t point_index_begin = num_points.fetch_add(sub_points.size());
85 for (
size_t i = 0; i < sub_points.size(); i++) {
size_t size(const T &points)
Get the number of points.
Definition: traits.hpp:16
auto point(const T &points, size_t i)
Get i-th point. 4D vector is used to take advantage of SIMD intrinsics. The last element must be fill...
Definition: traits.hpp:40
void set_point(T &points, size_t i, const Eigen::Vector4d &pt)
Set i-th point. (x, y, z, 1)
Definition: traits.hpp:64
void resize(T &points, size_t n)
Resize the point cloud (this function should resize all attributes)
Definition: traits.hpp:58
Definition: flat_container.hpp:12
std::shared_ptr< OutputPointCloud > voxelgrid_sampling_tbb(const InputPointCloud &points, double leaf_size)
Voxel grid downsampling with TBB backend.
Definition: downsampling_tbb.hpp:26