38 #ifndef PCL_FILTERS_IMPL_VOXEL_GRID_H_
39 #define PCL_FILTERS_IMPL_VOXEL_GRID_H_
45 template <
typename Po
intT>
void
47 const std::string &distance_field_name,
float min_distance,
float max_distance,
48 Eigen::Vector4f &min_pt, Eigen::Vector4f &max_pt,
bool limit_negative)
50 Eigen::Array4f min_p, max_p;
51 min_p.setConstant (FLT_MAX);
52 max_p.setConstant (-FLT_MAX);
55 std::vector<sensor_msgs::PointField> fields;
62 for (
size_t i = 0; i < cloud->
points.size (); ++i)
65 const uint8_t* pt_data =
reinterpret_cast<const uint8_t*
> (&cloud->
points[i]);
66 memcpy (&distance_value, pt_data + fields[distance_idx].offset,
sizeof (
float));
71 if ((distance_value < max_distance) && (distance_value > min_distance))
77 if ((distance_value > max_distance) || (distance_value < min_distance))
82 min_p = min_p.min (pt);
83 max_p = max_p.max (pt);
88 for (
size_t i = 0; i < cloud->
points.size (); ++i)
91 const uint8_t* pt_data =
reinterpret_cast<const uint8_t*
> (&cloud->
points[i]);
92 memcpy (&distance_value, pt_data + fields[distance_idx].offset,
sizeof (
float));
97 if ((distance_value < max_distance) && (distance_value > min_distance))
103 if ((distance_value > max_distance) || (distance_value < min_distance))
114 min_p = min_p.min (pt);
115 max_p = max_p.max (pt);
132 template <
typename Po
intT>
void
138 PCL_WARN (
"[pcl::%s::applyFilter] No input dataset given!\n", getClassName ().c_str ());
148 Eigen::Vector4f min_p, max_p;
150 if (!filter_field_name_.empty ())
151 getMinMax3D<PointT>(input_, filter_field_name_, static_cast<float> (filter_limit_min_),
static_cast<float> (filter_limit_max_), min_p, max_p, filter_limit_negative_);
153 getMinMax3D<PointT>(*input_, min_p, max_p);
156 min_b_[0] =
static_cast<int> (floor (min_p[0] * inverse_leaf_size_[0]));
157 max_b_[0] =
static_cast<int> (floor (max_p[0] * inverse_leaf_size_[0]));
158 min_b_[1] =
static_cast<int> (floor (min_p[1] * inverse_leaf_size_[1]));
159 max_b_[1] =
static_cast<int> (floor (max_p[1] * inverse_leaf_size_[1]));
160 min_b_[2] =
static_cast<int> (floor (min_p[2] * inverse_leaf_size_[2]));
161 max_b_[2] =
static_cast<int> (floor (max_p[2] * inverse_leaf_size_[2]));
164 div_b_ = max_b_ - min_b_ + Eigen::Vector4i::Ones ();
168 divb_mul_ = Eigen::Vector4i (1, div_b_[0], div_b_[0] * div_b_[1], 0);
170 int centroid_size = 4;
171 if (downsample_all_data_)
172 centroid_size = boost::mpl::size<FieldList>::value;
175 std::vector<sensor_msgs::PointField> fields;
178 if (rgba_index == -1)
182 rgba_index = fields[rgba_index].offset;
186 std::vector<cloud_point_index_idx> index_vector;
187 index_vector.reserve(input_->points.size());
190 if (!filter_field_name_.empty ())
193 std::vector<sensor_msgs::PointField> fields;
195 if (distance_idx == -1)
196 PCL_WARN (
"[pcl::%s::applyFilter] Invalid filter field name. Index is %d.\n", getClassName ().c_str (), distance_idx);
201 for (
unsigned int cp = 0; cp < static_cast<unsigned int> (input_->points.size ()); ++cp)
203 if (!input_->is_dense)
211 const uint8_t* pt_data =
reinterpret_cast<const uint8_t*
> (&input_->points[cp]);
212 float distance_value = 0;
213 memcpy (&distance_value, pt_data + fields[distance_idx].offset,
sizeof (
float));
215 if (filter_limit_negative_)
218 if ((distance_value < filter_limit_max_) && (distance_value > filter_limit_min_))
224 if ((distance_value > filter_limit_max_) || (distance_value < filter_limit_min_))
228 int ijk0 =
static_cast<int> (floor (input_->points[cp].x * inverse_leaf_size_[0]) - min_b_[0]);
229 int ijk1 =
static_cast<int> (floor (input_->points[cp].y * inverse_leaf_size_[1]) - min_b_[1]);
230 int ijk2 =
static_cast<int> (floor (input_->points[cp].z * inverse_leaf_size_[2]) - min_b_[2]);
233 int idx = ijk0 * divb_mul_[0] + ijk1 * divb_mul_[1] + ijk2 * divb_mul_[2];
243 for (
unsigned int cp = 0; cp < static_cast<unsigned int> (input_->points.size ()); ++cp)
245 if (!input_->is_dense)
252 int ijk0 =
static_cast<int> (floor (input_->points[cp].x * inverse_leaf_size_[0]) - min_b_[0]);
253 int ijk1 =
static_cast<int> (floor (input_->points[cp].y * inverse_leaf_size_[1]) - min_b_[1]);
254 int ijk2 =
static_cast<int> (floor (input_->points[cp].z * inverse_leaf_size_[2]) - min_b_[2]);
257 int idx = ijk0 * divb_mul_[0] + ijk1 * divb_mul_[1] + ijk2 * divb_mul_[2];
264 std::sort (index_vector.begin (), index_vector.end (), std::less<cloud_point_index_idx> ());
268 unsigned int total = 0;
269 unsigned int index = 0;
270 while (index < index_vector.size ())
272 unsigned int i = index + 1;
273 while (i < index_vector.size () && index_vector[i].idx == index_vector[index].idx)
280 output.
points.resize (total);
281 if (save_leaf_layout_)
286 uint32_t new_layout_size = div_b_[0]*div_b_[1]*div_b_[2];
288 uint32_t reinit_size = std::min (static_cast<unsigned int> (new_layout_size), static_cast<unsigned int> (leaf_layout_.size()));
289 for (uint32_t i = 0; i < reinit_size; i++)
291 leaf_layout_[i] = -1;
293 leaf_layout_.resize (new_layout_size, -1);
295 catch (std::bad_alloc&)
297 throw PCLException(
"VoxelGrid bin size is too low; impossible to allocate memory for layout",
298 "voxel_grid.hpp",
"applyFilter");
300 catch (std::length_error&)
302 throw PCLException(
"VoxelGrid bin size is too low; impossible to allocate memory for layout",
303 "voxel_grid.hpp",
"applyFilter");
308 Eigen::VectorXf centroid = Eigen::VectorXf::Zero (centroid_size);
309 Eigen::VectorXf temporary = Eigen::VectorXf::Zero (centroid_size);
311 for (
unsigned int cp = 0; cp < index_vector.size ();)
314 if (!downsample_all_data_)
316 centroid[0] = input_->points[index_vector[cp].cloud_point_index].x;
317 centroid[1] = input_->points[index_vector[cp].cloud_point_index].y;
318 centroid[2] = input_->points[index_vector[cp].cloud_point_index].z;
327 memcpy (&rgb, reinterpret_cast<const char*> (&input_->points[index_vector[cp].cloud_point_index]) + rgba_index, sizeof (RGB));
328 centroid[centroid_size-3] = rgb.r;
329 centroid[centroid_size-2] = rgb.g;
330 centroid[centroid_size-1] = rgb.b;
332 pcl::for_each_type <FieldList> (NdCopyPointEigenFunctor <PointT> (input_->points[index_vector[cp].cloud_point_index], centroid));
335 unsigned int i = cp + 1;
336 while (i < index_vector.size () && index_vector[i].idx == index_vector[cp].idx)
338 if (!downsample_all_data_)
340 centroid[0] += input_->points[index_vector[i].cloud_point_index].x;
341 centroid[1] += input_->points[index_vector[i].cloud_point_index].y;
342 centroid[2] += input_->points[index_vector[i].cloud_point_index].z;
351 memcpy (&rgb, reinterpret_cast<const char*> (&input_->points[index_vector[i].cloud_point_index]) + rgba_index, sizeof (RGB));
352 temporary[centroid_size-3] = rgb.r;
353 temporary[centroid_size-2] = rgb.g;
354 temporary[centroid_size-1] = rgb.b;
356 pcl::for_each_type <FieldList> (NdCopyPointEigenFunctor <PointT> (input_->points[index_vector[i].cloud_point_index], temporary));
357 centroid += temporary;
363 if (save_leaf_layout_)
364 leaf_layout_[index_vector[cp].idx] = index;
366 centroid /=
static_cast<float> (i - cp);
370 if (!downsample_all_data_)
372 output.
points[index].x = centroid[0];
373 output.
points[index].y = centroid[1];
374 output.
points[index].z = centroid[2];
383 float r = centroid[centroid_size-3], g = centroid[centroid_size-2], b = centroid[centroid_size-1];
384 int rgb = (
static_cast<int> (r) << 16) | (
static_cast<int> (g) << 8) |
static_cast<int> (b);
385 memcpy (reinterpret_cast<char*> (&output.
points[index]) + rgba_index, &rgb, sizeof (
float));
391 output.
width =
static_cast<uint32_t
> (output.
points.size ());
394 #define PCL_INSTANTIATE_VoxelGrid(T) template class PCL_EXPORTS pcl::VoxelGrid<T>;
395 #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);
397 #endif // PCL_FILTERS_IMPL_VOXEL_GRID_H_