25 template <
typename InputPo
intCloud, 
typename OutputPo
intCloud = InputPo
intCloud>
 
   26 std::shared_ptr<OutputPointCloud> 
voxelgrid_sampling_omp(
const InputPointCloud& points, 
double leaf_size, 
int num_threads = 4) {
 
   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 #pragma omp parallel for num_threads(num_threads) schedule(guided, 32) 
   40   for (std::int64_t i = 0; i < 
traits::size(points); i++) {
 
   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};
 
   48     const std::uint64_t bits =                                                           
 
   49       (
static_cast<std::uint64_t
>(coord[0] & coord_bit_mask) << (coord_bit_size * 0)) |  
 
   50       (
static_cast<std::uint64_t
>(coord[1] & coord_bit_mask) << (coord_bit_size * 1)) |  
 
   51       (
static_cast<std::uint64_t
>(coord[2] & coord_bit_mask) << (coord_bit_size * 2));
 
   52     coord_pt[i] = {bits, i};
 
   56   quick_sort_omp(coord_pt.begin(), coord_pt.end(), [](
const auto& lhs, 
const auto& rhs) { return lhs.first < rhs.first; }, num_threads);
 
   58   auto downsampled = std::make_shared<OutputPointCloud>();
 
   62   const int block_size = 1024;
 
   63   std::atomic_uint64_t num_points = 0;
 
   65 #pragma omp parallel for num_threads(num_threads) schedule(guided, 4) 
   66   for (std::int64_t block_begin = 0; block_begin < 
traits::size(points); block_begin += block_size) {
 
   67     std::vector<Eigen::Vector4d> sub_points;
 
   68     sub_points.reserve(block_size);
 
   70     const size_t block_end = std::min<size_t>(
traits::size(points), block_begin + block_size);
 
   72     Eigen::Vector4d sum_pt = 
traits::point(points, coord_pt[block_begin].second);
 
   73     for (
size_t i = block_begin + 1; i != block_end; i++) {
 
   74       if (coord_pt[i].first == invalid_coord) {
 
   78       if (coord_pt[i - 1].first != coord_pt[i].first) {
 
   79         sub_points.emplace_back(sum_pt / sum_pt.w());
 
   84     sub_points.emplace_back(sum_pt / sum_pt.w());
 
   86     const size_t point_index_begin = num_points.fetch_add(sub_points.size());
 
   87     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
 
void quick_sort_omp(RandomAccessIterator first, RandomAccessIterator last, const Compare &comp, int num_threads)
Quick sort with OpenMP parallelism.
Definition: sort_omp.hpp:95
 
Eigen::Array4i fast_floor(const Eigen::Array4d &pt)
Fast floor (https://stackoverflow.com/questions/824118/why-is-floor-so-slow).
Definition: fast_floor.hpp:12
 
std::shared_ptr< OutputPointCloud > voxelgrid_sampling_omp(const InputPointCloud &points, double leaf_size, int num_threads=4)
Voxel grid downsampling with OpenMP backend.
Definition: downsampling_omp.hpp:26