38 #ifndef PCL_FILTERS_IMPL_VOXEL_GRID_H_
39 #define PCL_FILTERS_IMPL_VOXEL_GRID_H_
41 #include <pcl/common/common.h>
42 #include <pcl/common/io.h>
43 #include <pcl/filters/voxel_grid.h>
46 template <
typename Po
intT>
void
48 const std::string &distance_field_name,
float min_distance,
float max_distance,
49 Eigen::Vector4f &min_pt, Eigen::Vector4f &max_pt,
bool limit_negative)
51 Eigen::Array4f min_p, max_p;
52 min_p.setConstant (FLT_MAX);
53 max_p.setConstant (-FLT_MAX);
56 std::vector<pcl::PCLPointField> fields;
63 for (
size_t i = 0; i < cloud->
points.size (); ++i)
66 const uint8_t* pt_data =
reinterpret_cast<const uint8_t*
> (&cloud->
points[i]);
67 memcpy (&distance_value, pt_data + fields[distance_idx].offset,
sizeof (
float));
72 if ((distance_value < max_distance) && (distance_value > min_distance))
78 if ((distance_value > max_distance) || (distance_value < min_distance))
83 min_p = min_p.min (pt);
84 max_p = max_p.max (pt);
89 for (
size_t i = 0; i < cloud->
points.size (); ++i)
92 const uint8_t* pt_data =
reinterpret_cast<const uint8_t*
> (&cloud->
points[i]);
93 memcpy (&distance_value, pt_data + fields[distance_idx].offset,
sizeof (
float));
98 if ((distance_value < max_distance) && (distance_value > min_distance))
104 if ((distance_value > max_distance) || (distance_value < min_distance))
109 if (!pcl_isfinite (cloud->
points[i].x) ||
110 !pcl_isfinite (cloud->
points[i].y) ||
111 !pcl_isfinite (cloud->
points[i].z))
115 min_p = min_p.min (pt);
116 max_p = max_p.max (pt);
124 template <
typename Po
intT>
void
126 const std::vector<int> &indices,
127 const std::string &distance_field_name,
float min_distance,
float max_distance,
128 Eigen::Vector4f &min_pt, Eigen::Vector4f &max_pt,
bool limit_negative)
130 Eigen::Array4f min_p, max_p;
131 min_p.setConstant (FLT_MAX);
132 max_p.setConstant (-FLT_MAX);
135 std::vector<pcl::PCLPointField> fields;
138 float distance_value;
142 for (std::vector<int>::const_iterator it = indices.begin (); it != indices.end (); ++it)
145 const uint8_t* pt_data =
reinterpret_cast<const uint8_t*
> (&cloud->
points[*it]);
146 memcpy (&distance_value, pt_data + fields[distance_idx].offset,
sizeof (
float));
151 if ((distance_value < max_distance) && (distance_value > min_distance))
157 if ((distance_value > max_distance) || (distance_value < min_distance))
162 min_p = min_p.min (pt);
163 max_p = max_p.max (pt);
168 for (std::vector<int>::const_iterator it = indices.begin (); it != indices.end (); ++it)
171 const uint8_t* pt_data =
reinterpret_cast<const uint8_t*
> (&cloud->
points[*it]);
172 memcpy (&distance_value, pt_data + fields[distance_idx].offset,
sizeof (
float));
177 if ((distance_value < max_distance) && (distance_value > min_distance))
183 if ((distance_value > max_distance) || (distance_value < min_distance))
188 if (!pcl_isfinite (cloud->
points[*it].x) ||
189 !pcl_isfinite (cloud->
points[*it].y) ||
190 !pcl_isfinite (cloud->
points[*it].z))
194 min_p = min_p.min (pt);
195 max_p = max_p.max (pt);
212 template <
typename Po
intT>
void
218 PCL_WARN (
"[pcl::%s::applyFilter] No input dataset given!\n", getClassName ().c_str ());
228 Eigen::Vector4f min_p, max_p;
230 if (!filter_field_name_.empty ())
231 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_);
233 getMinMax3D<PointT> (*input_, *indices_, min_p, max_p);
236 int64_t dx =
static_cast<int64_t
>((max_p[0] - min_p[0]) * inverse_leaf_size_[0])+1;
237 int64_t dy =
static_cast<int64_t
>((max_p[1] - min_p[1]) * inverse_leaf_size_[1])+1;
238 int64_t dz =
static_cast<int64_t
>((max_p[2] - min_p[2]) * inverse_leaf_size_[2])+1;
240 if( (dx*dy*dz) >
static_cast<int64_t
>(std::numeric_limits<int32_t>::max()) )
242 PCL_WARN(
"[pcl::%s::applyFilter] Leaf size is too small for the input dataset. Integer indices would overflow.", getClassName().c_str());
248 min_b_[0] =
static_cast<int> (floor (min_p[0] * inverse_leaf_size_[0]));
249 max_b_[0] =
static_cast<int> (floor (max_p[0] * inverse_leaf_size_[0]));
250 min_b_[1] =
static_cast<int> (floor (min_p[1] * inverse_leaf_size_[1]));
251 max_b_[1] =
static_cast<int> (floor (max_p[1] * inverse_leaf_size_[1]));
252 min_b_[2] =
static_cast<int> (floor (min_p[2] * inverse_leaf_size_[2]));
253 max_b_[2] =
static_cast<int> (floor (max_p[2] * inverse_leaf_size_[2]));
256 div_b_ = max_b_ - min_b_ + Eigen::Vector4i::Ones ();
260 divb_mul_ = Eigen::Vector4i (1, div_b_[0], div_b_[0] * div_b_[1], 0);
262 int centroid_size = 4;
263 if (downsample_all_data_)
264 centroid_size = boost::mpl::size<FieldList>::value;
267 std::vector<pcl::PCLPointField> fields;
270 if (rgba_index == -1)
274 rgba_index = fields[rgba_index].offset;
278 std::vector<cloud_point_index_idx> index_vector;
279 index_vector.reserve (indices_->size ());
282 if (!filter_field_name_.empty ())
285 std::vector<pcl::PCLPointField> fields;
287 if (distance_idx == -1)
288 PCL_WARN (
"[pcl::%s::applyFilter] Invalid filter field name. Index is %d.\n", getClassName ().c_str (), distance_idx);
293 for (std::vector<int>::const_iterator it = indices_->begin (); it != indices_->end (); ++it)
295 if (!input_->is_dense)
297 if (!pcl_isfinite (input_->points[*it].x) ||
298 !pcl_isfinite (input_->points[*it].y) ||
299 !pcl_isfinite (input_->points[*it].z))
303 const uint8_t* pt_data =
reinterpret_cast<const uint8_t*
> (&input_->points[*it]);
304 float distance_value = 0;
305 memcpy (&distance_value, pt_data + fields[distance_idx].offset,
sizeof (
float));
307 if (filter_limit_negative_)
310 if ((distance_value < filter_limit_max_) && (distance_value > filter_limit_min_))
316 if ((distance_value > filter_limit_max_) || (distance_value < filter_limit_min_))
320 int ijk0 =
static_cast<int> (floor (input_->points[*it].x * inverse_leaf_size_[0]) -
static_cast<float> (min_b_[0]));
321 int ijk1 =
static_cast<int> (floor (input_->points[*it].y * inverse_leaf_size_[1]) -
static_cast<float> (min_b_[1]));
322 int ijk2 =
static_cast<int> (floor (input_->points[*it].z * inverse_leaf_size_[2]) -
static_cast<float> (min_b_[2]));
325 int idx = ijk0 * divb_mul_[0] + ijk1 * divb_mul_[1] + ijk2 * divb_mul_[2];
335 for (std::vector<int>::const_iterator it = indices_->begin (); it != indices_->end (); ++it)
337 if (!input_->is_dense)
339 if (!pcl_isfinite (input_->points[*it].x) ||
340 !pcl_isfinite (input_->points[*it].y) ||
341 !pcl_isfinite (input_->points[*it].z))
344 int ijk0 =
static_cast<int> (floor (input_->points[*it].x * inverse_leaf_size_[0]) -
static_cast<float> (min_b_[0]));
345 int ijk1 =
static_cast<int> (floor (input_->points[*it].y * inverse_leaf_size_[1]) -
static_cast<float> (min_b_[1]));
346 int ijk2 =
static_cast<int> (floor (input_->points[*it].z * inverse_leaf_size_[2]) -
static_cast<float> (min_b_[2]));
349 int idx = ijk0 * divb_mul_[0] + ijk1 * divb_mul_[1] + ijk2 * divb_mul_[2];
356 std::sort (index_vector.begin (), index_vector.end (), std::less<cloud_point_index_idx> ());
360 unsigned int total = 0;
361 unsigned int index = 0;
362 while (index < index_vector.size ())
364 unsigned int i = index + 1;
365 while (i < index_vector.size () && index_vector[i].idx == index_vector[index].idx)
372 output.
points.resize (total);
373 if (save_leaf_layout_)
378 uint32_t new_layout_size = div_b_[0]*div_b_[1]*div_b_[2];
380 uint32_t reinit_size = std::min (static_cast<unsigned int> (new_layout_size), static_cast<unsigned int> (leaf_layout_.size()));
381 for (uint32_t i = 0; i < reinit_size; i++)
383 leaf_layout_[i] = -1;
385 leaf_layout_.resize (new_layout_size, -1);
387 catch (std::bad_alloc&)
389 throw PCLException(
"VoxelGrid bin size is too low; impossible to allocate memory for layout",
390 "voxel_grid.hpp",
"applyFilter");
392 catch (std::length_error&)
394 throw PCLException(
"VoxelGrid bin size is too low; impossible to allocate memory for layout",
395 "voxel_grid.hpp",
"applyFilter");
400 Eigen::VectorXf centroid = Eigen::VectorXf::Zero (centroid_size);
401 Eigen::VectorXf temporary = Eigen::VectorXf::Zero (centroid_size);
403 for (
unsigned int cp = 0; cp < index_vector.size ();)
406 if (!downsample_all_data_)
408 centroid[0] = input_->points[index_vector[cp].cloud_point_index].x;
409 centroid[1] = input_->points[index_vector[cp].cloud_point_index].y;
410 centroid[2] = input_->points[index_vector[cp].cloud_point_index].z;
419 memcpy (&rgb, reinterpret_cast<const char*> (&input_->points[index_vector[cp].cloud_point_index]) + rgba_index, sizeof (
RGB));
420 centroid[centroid_size-3] = rgb.r;
421 centroid[centroid_size-2] = rgb.g;
422 centroid[centroid_size-1] = rgb.b;
427 unsigned int i = cp + 1;
428 while (i < index_vector.size () && index_vector[i].idx == index_vector[cp].idx)
430 if (!downsample_all_data_)
432 centroid[0] += input_->points[index_vector[i].cloud_point_index].x;
433 centroid[1] += input_->points[index_vector[i].cloud_point_index].y;
434 centroid[2] += input_->points[index_vector[i].cloud_point_index].z;
443 memcpy (&rgb, reinterpret_cast<const char*> (&input_->points[index_vector[i].cloud_point_index]) + rgba_index, sizeof (
RGB));
444 temporary[centroid_size-3] = rgb.r;
445 temporary[centroid_size-2] = rgb.g;
446 temporary[centroid_size-1] = rgb.b;
449 centroid += temporary;
455 if (save_leaf_layout_)
456 leaf_layout_[index_vector[cp].idx] = index;
458 centroid /=
static_cast<float> (i - cp);
462 if (!downsample_all_data_)
464 output.
points[index].x = centroid[0];
465 output.
points[index].y = centroid[1];
466 output.
points[index].z = centroid[2];
475 float r = centroid[centroid_size-3], g = centroid[centroid_size-2], b = centroid[centroid_size-1];
476 int rgb = (
static_cast<int> (r) << 16) | (
static_cast<int> (g) << 8) |
static_cast<int> (b);
477 memcpy (reinterpret_cast<char*> (&output.
points[index]) + rgba_index, &rgb, sizeof (
float));
483 output.
width =
static_cast<uint32_t
> (output.
points.size ());
486 #define PCL_INSTANTIATE_VoxelGrid(T) template class PCL_EXPORTS pcl::VoxelGrid<T>;
487 #define PCL_INSTANTIATE_getMinMax3D(T) template PCL_EXPORTS void pcl::getMinMax3D<T> (const pcl::PointCloud<T>::ConstPtr &, const std::string &, float, float, Eigen::Vector4f &, Eigen::Vector4f &, bool);
489 #endif // PCL_FILTERS_IMPL_VOXEL_GRID_H_
void getMinMax3D(const pcl::PointCloud< PointT > &cloud, PointT &min_pt, PointT &max_pt)
Get the minimum and maximum values on each of the 3 (x-y-z) dimensions in a given pointcloud...
int getFieldIndex(const pcl::PCLPointCloud2 &cloud, const std::string &field_name)
Get the index of a specified field (i.e., dimension/channel)
uint32_t width
The point cloud width (if organized as an image-structure).
bool operator<(const cloud_point_index_idx &p) const
A base class for all pcl exceptions which inherits from std::runtime_error.
void applyFilter(PointCloud &output)
Downsample a Point Cloud using a voxelized grid approach.
A structure representing RGB color information.
Helper functor structure for copying data between an Eigen type and a PointT.
uint32_t height
The point cloud height (if organized as an image-structure).
cloud_point_index_idx(unsigned int idx_, unsigned int cloud_point_index_)
std::vector< PointT, Eigen::aligned_allocator< PointT > > points
The point data.
boost::shared_ptr< const PointCloud< PointT > > ConstPtr
bool is_dense
True if no points are invalid (e.g., have NaN or Inf values).
const Eigen::Map< const Eigen::Array4f, Eigen::Aligned > Array4fMapConst
unsigned int cloud_point_index
Helper functor structure for copying data between an Eigen type and a PointT.