Point Cloud Library (PCL)  1.15.1-dev
point_cloud.h
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Point Cloud Library (PCL) - www.pointclouds.org
5  * Copyright (c) 2010-2012, Willow Garage, Inc.
6  * Copyright (c) 2012-, Open Perception, Inc.
7  *
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  *
14  * * Redistributions of source code must retain the above copyright
15  * notice, this list of conditions and the following disclaimer.
16  * * Redistributions in binary form must reproduce the above
17  * copyright notice, this list of conditions and the following
18  * disclaimer in the documentation and/or other materials provided
19  * with the distribution.
20  * * Neither the name of the copyright holder(s) nor the names of its
21  * contributors may be used to endorse or promote products derived
22  * from this software without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35  * POSSIBILITY OF SUCH DAMAGE.
36  *
37  */
38 
39 #pragma once
40 
41 #ifdef __GNUC__
42 #pragma GCC system_header
43 #endif
44 
45 #include <Eigen/StdVector>
46 #include <Eigen/Geometry>
47 #include <pcl/PCLHeader.h>
48 #include <pcl/exceptions.h>
49 #include <pcl/memory.h>
50 #include <pcl/pcl_macros.h>
51 #include <pcl/type_traits.h>
52 #include <pcl/types.h>
53 #include <pcl/console/print.h> // for PCL_WARN
54 
55 #include <cassert> // for assert
56 #include <utility>
57 #include <vector>
58 
59 namespace pcl
60 {
61  namespace detail
62  {
63  struct FieldMapping
64  {
65  std::size_t serialized_offset;
66  std::size_t struct_offset;
67  std::size_t size;
68  };
69  } // namespace detail
70 
71  // Forward declarations
72  template <typename PointT> class PointCloud;
73  using MsgFieldMap = std::vector<detail::FieldMapping>;
74 
75  /** \brief Helper functor structure for copying data between an Eigen type and a PointT. */
76  template <typename PointOutT>
78  {
79  using Pod = typename traits::POD<PointOutT>::type;
80 
81  /** \brief Constructor
82  * \param[in] p1 the input Eigen type
83  * \param[out] p2 the output Point type
84  */
85  NdCopyEigenPointFunctor (const Eigen::VectorXf &p1, PointOutT &p2)
86  : p1_ (p1),
87  p2_ (reinterpret_cast<Pod&>(p2)),
88  f_idx_ (0) { }
89 
90  /** \brief Operator. Data copy happens here. */
91  template<typename Key> inline void
93  {
94  //boost::fusion::at_key<Key> (p2_) = p1_[f_idx_++];
95  using T = typename pcl::traits::datatype<PointOutT, Key>::type;
96  std::uint8_t* data_ptr = reinterpret_cast<std::uint8_t*>(&p2_) + pcl::traits::offset<PointOutT, Key>::value;
97  *reinterpret_cast<T*>(data_ptr) = static_cast<T> (p1_[f_idx_++]);
98  }
99 
100  private:
101  const Eigen::VectorXf &p1_;
102  Pod &p2_;
103  int f_idx_;
104  public:
106  };
107 
108  /** \brief Helper functor structure for copying data between an Eigen type and a PointT. */
109  template <typename PointInT>
111  {
112  using Pod = typename traits::POD<PointInT>::type;
113 
114  /** \brief Constructor
115  * \param[in] p1 the input Point type
116  * \param[out] p2 the output Eigen type
117  */
118  NdCopyPointEigenFunctor (const PointInT &p1, Eigen::VectorXf &p2)
119  : p1_ (reinterpret_cast<const Pod&>(p1)), p2_ (p2), f_idx_ (0) { }
120 
121  /** \brief Operator. Data copy happens here. */
122  template<typename Key> inline void
124  {
125  //p2_[f_idx_++] = boost::fusion::at_key<Key> (p1_);
126  using T = typename pcl::traits::datatype<PointInT, Key>::type;
127  const std::uint8_t* data_ptr = reinterpret_cast<const std::uint8_t*>(&p1_) + pcl::traits::offset<PointInT, Key>::value;
128  p2_[f_idx_++] = static_cast<float> (*reinterpret_cast<const T*>(data_ptr));
129  }
130 
131  private:
132  const Pod &p1_;
133  Eigen::VectorXf &p2_;
134  int f_idx_;
135  public:
137  };
138 
139  /** \brief PointCloud represents the base class in PCL for storing collections of 3D points.
140  *
141  * The class is templated, which means you need to specify the type of data
142  * that it should contain. For example, to create a point cloud that holds 4
143  * random XYZ data points, use:
144  *
145  * \code
146  * pcl::PointCloud<pcl::PointXYZ> cloud;
147  * cloud.push_back (pcl::PointXYZ (rand (), rand (), rand ()));
148  * cloud.push_back (pcl::PointXYZ (rand (), rand (), rand ()));
149  * cloud.push_back (pcl::PointXYZ (rand (), rand (), rand ()));
150  * cloud.push_back (pcl::PointXYZ (rand (), rand (), rand ()));
151  * \endcode
152  *
153  * The PointCloud class contains the following elements:
154  * - \b width - specifies the width of the point cloud dataset in the number of points. WIDTH has two meanings:
155  * - it can specify the total number of points in the cloud (equal with POINTS see below) for unorganized datasets;
156  * - it can specify the width (total number of points in a row) of an organized point cloud dataset.
157  * \a Mandatory.
158  * - \b height - specifies the height of the point cloud dataset in the number of points. HEIGHT has two meanings:
159  * - it can specify the height (total number of rows) of an organized point cloud dataset;
160  * - it is set to 1 for unorganized datasets (thus used to check whether a dataset is organized or not).
161  * \a Mandatory.
162  * - \b points - the data array where all points of type <b>PointT</b> are stored. \a Mandatory.
163  *
164  * - \b is_dense - specifies if all the data in <b>points</b> is finite (true), or whether it might contain Inf/NaN values
165  * (false). \a Mandatory.
166  *
167  * - \b sensor_origin_ - specifies the sensor acquisition pose (origin/translation). \a Optional.
168  * - \b sensor_orientation_ - specifies the sensor acquisition pose (rotation). \a Optional.
169  *
170  * \author Patrick Mihelich, Radu B. Rusu
171  */
172  template <typename PointT>
174  {
175  public:
176  /** \brief Default constructor. Sets \ref is_dense to true, \ref width
177  * and \ref height to 0, and the \ref sensor_origin_ and \ref
178  * sensor_orientation_ to identity.
179  */
180  PointCloud () = default;
181 
182  /** \brief Copy constructor from point cloud subset
183  * \param[in] pc the cloud to copy into this
184  * \param[in] indices the subset to copy
185  */
187  const Indices &indices) :
188  header (pc.header), points (indices.size ()), width (indices.size ()), height (1), is_dense (pc.is_dense),
190  {
191  // Copy the obvious
192  assert (indices.size () <= pc.size ());
193  for (std::size_t i = 0; i < indices.size (); i++)
194  points[i] = pc[indices[i]];
195  }
196 
197  /** \brief Allocate constructor from point cloud subset
198  * \param[in] width_ the cloud width
199  * \param[in] height_ the cloud height
200  * \param[in] value_ default value
201  */
202  PointCloud (std::uint32_t width_, std::uint32_t height_, const PointT& value_ = PointT ())
203  : points (width_ * height_, value_)
204  , width (width_)
205  , height (height_)
206  {}
207 
208  //TODO: check if copy/move constructors/assignment operators are needed
209 
210  /** \brief Add a point cloud to the current cloud.
211  * \param[in] rhs the cloud to add to the current cloud
212  * \return the new cloud as a concatenation of the current cloud and the new given cloud
213  */
214  inline PointCloud&
216  {
217  concatenate((*this), rhs);
218  return (*this);
219  }
220 
221  /** \brief Add a point cloud to another cloud.
222  * \param[in] rhs the cloud to add to the current cloud
223  * \return the new cloud as a concatenation of the current cloud and the new given cloud
224  */
225  inline PointCloud
227  {
228  return (PointCloud (*this) += rhs);
229  }
230 
231  inline static bool
233  const pcl::PointCloud<PointT> &cloud2)
234  {
235  // Make the resultant point cloud take the newest stamp
236  cloud1.header.stamp = std::max (cloud1.header.stamp, cloud2.header.stamp);
237 
238  // libstdc++ (GCC) on calling reserve allocates new memory, copies and deallocates old vector
239  // This causes a drastic performance hit. Prefer not to use reserve with libstdc++ (default on clang)
240  cloud1.insert (cloud1.end (), cloud2.begin (), cloud2.end ());
241 
242  cloud1.width = cloud1.size ();
243  cloud1.height = 1;
244  cloud1.is_dense = cloud1.is_dense && cloud2.is_dense;
245  return true;
246  }
247 
248  inline static bool
250  const pcl::PointCloud<PointT> &cloud2,
251  pcl::PointCloud<PointT> &cloud_out)
252  {
253  cloud_out = cloud1;
254  return concatenate(cloud_out, cloud2);
255  }
256 
257  /** \brief Obtain the point given by the (column, row) coordinates. Only works on organized
258  * datasets (those that have height != 1).
259  * \param[in] column the column coordinate
260  * \param[in] row the row coordinate
261  */
262  inline const PointT&
263  at (int column, int row) const
264  {
265  if (this->height > 1)
266  return (points.at (row * this->width + column));
267  else
268  throw UnorganizedPointCloudException ("Can't use 2D indexing with an unorganized point cloud");
269  }
270 
271  /** \brief Obtain the point given by the (column, row) coordinates. Only works on organized
272  * datasets (those that have height != 1).
273  * \param[in] column the column coordinate
274  * \param[in] row the row coordinate
275  */
276  inline PointT&
277  at (int column, int row)
278  {
279  if (this->height > 1)
280  return (points.at (row * this->width + column));
281  else
282  throw UnorganizedPointCloudException ("Can't use 2D indexing with an unorganized point cloud");
283  }
284 
285  /** \brief Obtain the point given by the (column, row) coordinates. Only works on organized
286  * datasets (those that have height != 1).
287  * \param[in] column the column coordinate
288  * \param[in] row the row coordinate
289  */
290  inline const PointT&
291  operator () (std::size_t column, std::size_t row) const
292  {
293  return (points[row * this->width + column]);
294  }
295 
296  /** \brief Obtain the point given by the (column, row) coordinates. Only works on organized
297  * datasets (those that have height != 1).
298  * \param[in] column the column coordinate
299  * \param[in] row the row coordinate
300  */
301  inline PointT&
302  operator () (std::size_t column, std::size_t row)
303  {
304  return (points[row * this->width + column]);
305  }
306 
307  /** \brief Return whether a dataset is organized (e.g., arranged in a structured grid).
308  * \note The height value must be different than 1 for a dataset to be organized.
309  */
310  inline bool
311  isOrganized () const
312  {
313  return (height > 1);
314  }
315 
316  /** \brief Return an Eigen MatrixXf (assumes float values) mapped to the specified dimensions of the PointCloud.
317  * \note This method is for advanced users only! Use with care!
318  *
319  * \attention Compile time flags used for Eigen might affect the dimension of the Eigen::Map returned. If Eigen
320  * is using row major storage, the matrix shape would be (number of Points X elements in a Point) else
321  * the matrix shape would be (elements in a Point X number of Points). Essentially,
322  * * Major direction: number of points in cloud
323  * * Minor direction: number of point dimensions
324  * By default, as of Eigen 3.3, Eigen uses Column major storage
325  *
326  * \param[in] dim the number of dimensions to consider for each point
327  * \param[in] stride the number of values in each point (will be the number of values that separate two of the columns)
328  * \param[in] offset the number of dimensions to skip from the beginning of each point
329  * (stride = offset + dim + x, where x is the number of dimensions to skip from the end of each point)
330  * \note for getting only XYZ coordinates out of PointXYZ use dim=3, stride=4 and offset=0 due to the alignment.
331  * \attention PointT types are most of the time aligned, so the offsets are not continuous!
332  */
333  inline Eigen::Map<Eigen::MatrixXf, Eigen::Aligned, Eigen::OuterStride<> >
334  getMatrixXfMap (int dim, int stride, int offset)
335  {
336  if (Eigen::MatrixXf::Flags & Eigen::RowMajorBit)
337  return (Eigen::Map<Eigen::MatrixXf, Eigen::Aligned, Eigen::OuterStride<> >(reinterpret_cast<float*>(&points[0])+offset, size (), dim, Eigen::OuterStride<> (stride)));
338  else
339  return (Eigen::Map<Eigen::MatrixXf, Eigen::Aligned, Eigen::OuterStride<> >(reinterpret_cast<float*>(&points[0])+offset, dim, size (), Eigen::OuterStride<> (stride)));
340  }
341 
342  /** \brief Return an Eigen MatrixXf (assumes float values) mapped to the specified dimensions of the PointCloud.
343  * \note This method is for advanced users only! Use with care!
344  *
345  * \attention Compile time flags used for Eigen might affect the dimension of the Eigen::Map returned. If Eigen
346  * is using row major storage, the matrix shape would be (number of Points X elements in a Point) else
347  * the matrix shape would be (elements in a Point X number of Points). Essentially,
348  * * Major direction: number of points in cloud
349  * * Minor direction: number of point dimensions
350  * By default, as of Eigen 3.3, Eigen uses Column major storage
351  *
352  * \param[in] dim the number of dimensions to consider for each point
353  * \param[in] stride the number of values in each point (will be the number of values that separate two of the columns)
354  * \param[in] offset the number of dimensions to skip from the beginning of each point
355  * (stride = offset + dim + x, where x is the number of dimensions to skip from the end of each point)
356  * \note for getting only XYZ coordinates out of PointXYZ use dim=3, stride=4 and offset=0 due to the alignment.
357  * \attention PointT types are most of the time aligned, so the offsets are not continuous!
358  */
359  inline const Eigen::Map<const Eigen::MatrixXf, Eigen::Aligned, Eigen::OuterStride<> >
360  getMatrixXfMap (int dim, int stride, int offset) const
361  {
362  if (Eigen::MatrixXf::Flags & Eigen::RowMajorBit)
363  return (Eigen::Map<const Eigen::MatrixXf, Eigen::Aligned, Eigen::OuterStride<> >(reinterpret_cast<float*>(const_cast<PointT*>(&points[0]))+offset, size (), dim, Eigen::OuterStride<> (stride)));
364  else
365  return (Eigen::Map<const Eigen::MatrixXf, Eigen::Aligned, Eigen::OuterStride<> >(reinterpret_cast<float*>(const_cast<PointT*>(&points[0]))+offset, dim, size (), Eigen::OuterStride<> (stride)));
366  }
367 
368  /**
369  * \brief Return an Eigen MatrixXf (assumes float values) mapped to the PointCloud.
370  * \note This method is for advanced users only! Use with care!
371  * \attention PointT types are most of the time aligned, so the offsets are not continuous!
372  * \overload Eigen::Map<Eigen::MatrixXf, Eigen::Aligned, Eigen::OuterStride<> > pcl::PointCloud::getMatrixXfMap ()
373  */
374  inline Eigen::Map<Eigen::MatrixXf, Eigen::Aligned, Eigen::OuterStride<> >
376  {
377  return (getMatrixXfMap (sizeof (PointT) / sizeof (float), sizeof (PointT) / sizeof (float), 0));
378  }
379 
380  /**
381  * \brief Return an Eigen MatrixXf (assumes float values) mapped to the PointCloud.
382  * \note This method is for advanced users only! Use with care!
383  * \attention PointT types are most of the time aligned, so the offsets are not continuous!
384  * \overload const Eigen::Map<Eigen::MatrixXf, Eigen::Aligned, Eigen::OuterStride<> > pcl::PointCloud::getMatrixXfMap () const
385  */
386  inline const Eigen::Map<const Eigen::MatrixXf, Eigen::Aligned, Eigen::OuterStride<> >
387  getMatrixXfMap () const
388  {
389  return (getMatrixXfMap (sizeof (PointT) / sizeof (float), sizeof (PointT) / sizeof (float), 0));
390  }
391 
392  /** \brief The point cloud header. It contains information about the acquisition time. */
394 
395  /** \brief The point data. */
396  std::vector<PointT, Eigen::aligned_allocator<PointT> > points;
397 
398  /** \brief The point cloud width (if organized as an image-structure). */
399  std::uint32_t width = 0;
400  /** \brief The point cloud height (if organized as an image-structure). */
401  std::uint32_t height = 0;
402 
403  /** \brief True if no points are invalid (e.g., have NaN or Inf values in any of their floating point fields). */
404  bool is_dense = true;
405 
406  /** \brief Sensor acquisition pose (origin/translation). */
407  Eigen::Vector4f sensor_origin_ = Eigen::Vector4f::Zero ();
408  /** \brief Sensor acquisition pose (rotation). */
409  Eigen::Quaternionf sensor_orientation_ = Eigen::Quaternionf::Identity ();
410 
411  using PointType = PointT; // Make the template class available from the outside
412  using VectorType = std::vector<PointT, Eigen::aligned_allocator<PointT> >;
413  using CloudVectorType = std::vector<PointCloud<PointT>, Eigen::aligned_allocator<PointCloud<PointT> > >;
414  using Ptr = shared_ptr<PointCloud<PointT> >;
415  using ConstPtr = shared_ptr<const PointCloud<PointT> >;
416 
417  // std container compatibility typedefs according to
418  // http://en.cppreference.com/w/cpp/concept/Container
420  using reference = PointT&;
421  using const_reference = const PointT&;
422  using difference_type = typename VectorType::difference_type;
423  using size_type = typename VectorType::size_type;
424 
425  // iterators
426  using iterator = typename VectorType::iterator;
427  using const_iterator = typename VectorType::const_iterator;
428  using reverse_iterator = typename VectorType::reverse_iterator;
429  using const_reverse_iterator = typename VectorType::const_reverse_iterator;
430  inline iterator begin () noexcept { return (points.begin ()); }
431  inline iterator end () noexcept { return (points.end ()); }
432  inline const_iterator begin () const noexcept { return (points.begin ()); }
433  inline const_iterator end () const noexcept { return (points.end ()); }
434  inline const_iterator cbegin () const noexcept { return (points.cbegin ()); }
435  inline const_iterator cend () const noexcept { return (points.cend ()); }
436  inline reverse_iterator rbegin () noexcept { return (points.rbegin ()); }
437  inline reverse_iterator rend () noexcept { return (points.rend ()); }
438  inline const_reverse_iterator rbegin () const noexcept { return (points.rbegin ()); }
439  inline const_reverse_iterator rend () const noexcept { return (points.rend ()); }
440  inline const_reverse_iterator crbegin () const noexcept { return (points.crbegin ()); }
441  inline const_reverse_iterator crend () const noexcept { return (points.crend ()); }
442 
443  //capacity
444  inline std::size_t size () const { return points.size (); }
445  inline index_t max_size() const noexcept { return static_cast<index_t>(points.max_size()); }
446  inline void reserve (std::size_t n) { points.reserve (n); }
447  inline bool empty () const { return points.empty (); }
448  inline PointT* data() noexcept { return points.data(); }
449  inline const PointT* data() const noexcept { return points.data(); }
450 
451  /**
452  * \brief Resizes the container to contain `count` elements
453  * \details
454  * * If the current size is greater than `count`, the pointcloud is reduced to its
455  * first `count` elements
456  * * If the current size is less than `count`, additional default-inserted points
457  * are appended
458  * \note This potentially breaks the organized structure of the cloud by setting
459  * the height to 1 IFF `width * height != count`!
460  * \param[in] count new size of the point cloud
461  */
462  inline void
463  resize(std::size_t count)
464  {
465  points.resize(count);
466  if (width * height != count) {
467  width = static_cast<std::uint32_t>(count);
468  height = 1;
469  }
470  }
471 
472  /**
473  * \brief Resizes the container to contain `new_width * new_height` elements
474  * \details
475  * * If the current size is greater than the requested size, the pointcloud
476  * is reduced to its first requested elements
477  * * If the current size is less then the requested size, additional
478  * default-inserted points are appended
479  * \param[in] new_width new width of the point cloud
480  * \param[in] new_height new height of the point cloud
481  */
482  inline void
483  resize(uindex_t new_width, uindex_t new_height)
484  {
485  points.resize(new_width * new_height);
486  width = new_width;
487  height = new_height;
488  }
489 
490  /**
491  * \brief Resizes the container to contain count elements
492  * \details
493  * * If the current size is greater than `count`, the pointcloud is reduced to its
494  * first `count` elements
495  * * If the current size is less than `count`, additional copies of `value` are
496  * appended
497  * \note This potentially breaks the organized structure of the cloud by setting
498  * the height to 1 IFF `width * height != count`!
499  * \param[in] count new size of the point cloud
500  * \param[in] value the value to initialize the new points with
501  */
502  inline void
503  resize(index_t count, const PointT& value)
504  {
505  points.resize(count, value);
506  if (width * height != count) {
507  width = count;
508  height = 1;
509  }
510  }
511 
512  /**
513  * \brief Resizes the container to contain count elements
514  * \details
515  * * If the current size is greater then the requested size, the pointcloud
516  * is reduced to its first requested elements
517  * * If the current size is less then the requested size, additional
518  * default-inserted points are appended
519  * \param[in] new_width new width of the point cloud
520  * \param[in] new_height new height of the point cloud
521  * \param[in] value the value to initialize the new points with
522  */
523  inline void
524  resize(index_t new_width, index_t new_height, const PointT& value)
525  {
526  points.resize(new_width * new_height, value);
527  width = new_width;
528  height = new_height;
529  }
530 
531  //element access
532  inline const PointT& operator[] (std::size_t n) const { return (points[n]); }
533  inline PointT& operator[] (std::size_t n) { return (points[n]); }
534  inline const PointT& at (std::size_t n) const { return (points.at (n)); }
535  inline PointT& at (std::size_t n) { return (points.at (n)); }
536  inline const PointT& front () const { return (points.front ()); }
537  inline PointT& front () { return (points.front ()); }
538  inline const PointT& back () const { return (points.back ()); }
539  inline PointT& back () { return (points.back ()); }
540 
541  /**
542  * \brief Replaces the points with `count` copies of `value`
543  * \note This breaks the organized structure of the cloud by setting the height to
544  * 1!
545  * \param[in] count new size of the point cloud
546  * \param[in] value value each point of the cloud should have
547  */
548  inline void
549  assign(index_t count, const PointT& value)
550  {
551  points.assign(count, value);
552  width = static_cast<std::uint32_t>(size());
553  height = 1;
554  }
555 
556  /**
557  * \brief Replaces the points with `new_width * new_height` copies of `value`
558  * \param[in] new_width new width of the point cloud
559  * \param[in] new_height new height of the point cloud
560  * \param[in] value value each point of the cloud should have
561  */
562  inline void
563  assign(index_t new_width, index_t new_height, const PointT& value)
564  {
565  points.assign(new_width * new_height, value);
566  width = new_width;
567  height = new_height;
568  }
569 
570  /**
571  * \brief Replaces the points with copies of those in the range `[first, last)`
572  * \details The behavior is undefined if either argument is an iterator into
573  * `*this`
574  * \note This breaks the organized structure of the cloud by setting the height to
575  * 1!
576  */
577  template <class InputIterator>
578  inline void
579  assign(InputIterator first, InputIterator last)
580  {
581  points.assign(std::move(first), std::move(last));
582  width = static_cast<std::uint32_t>(size());
583  height = 1;
584  }
585 
586  /**
587  * \brief Replaces the points with copies of those in the range `[first, last)`
588  * \details The behavior is undefined if either argument is an iterator into
589  * `*this`
590  * \note This calculates the height based on size and width provided. This means
591  * the assignment happens even if the size is not perfectly divisible by width
592  * \param[in] first, last the range from which the points are copied
593  * \param[in] new_width new width of the point cloud
594  */
595  template <class InputIterator>
596  inline void
597  assign(InputIterator first, InputIterator last, index_t new_width)
598  {
599  if (new_width == 0) {
600  PCL_WARN("Assignment with new_width equal to 0,"
601  "setting width to size of the cloud and height to 1\n");
602  return assign(std::move(first), std::move(last));
603  }
604 
605  points.assign(std::move(first), std::move(last));
606  width = new_width;
607  height = size() / width;
608  if (width * height != size()) {
609  PCL_WARN("Mismatch in assignment. Requested width (%zu) doesn't divide "
610  "provided size (%zu) cleanly. Setting height to 1\n",
611  static_cast<std::size_t>(width),
612  static_cast<std::size_t>(size()));
613  width = size();
614  height = 1;
615  }
616  }
617 
618  /**
619  * \brief Replaces the points with the elements from the initializer list `ilist`
620  * \note This breaks the organized structure of the cloud by setting the height to
621  * 1!
622  */
623  void
624  inline assign(std::initializer_list<PointT> ilist)
625  {
626  points.assign(std::move(ilist));
627  width = static_cast<std::uint32_t>(size());
628  height = 1;
629  }
630 
631  /**
632  * \brief Replaces the points with the elements from the initializer list `ilist`
633  * \note This calculates the height based on size and width provided. This means
634  * the assignment happens even if the size is not perfectly divisible by width
635  * \param[in] ilist initializer list from which the points are copied
636  * \param[in] new_width new width of the point cloud
637  */
638  void
639  inline assign(std::initializer_list<PointT> ilist, index_t new_width)
640  {
641  if (new_width == 0) {
642  PCL_WARN("Assignment with new_width equal to 0,"
643  "setting width to size of the cloud and height to 1\n");
644  return assign(std::move(ilist));
645  }
646  points.assign(std::move(ilist));
647  width = new_width;
648  height = size() / width;
649  if (width * height != size()) {
650  PCL_WARN("Mismatch in assignment. Requested width (%zu) doesn't divide "
651  "provided size (%zu) cleanly. Setting height to 1\n",
652  static_cast<std::size_t>(width),
653  static_cast<std::size_t>(size()));
654  width = size();
655  height = 1;
656  }
657  }
658 
659  /** \brief Insert a new point in the cloud, at the end of the container.
660  * \note This breaks the organized structure of the cloud by setting the height to 1!
661  * \param[in] pt the point to insert
662  */
663  inline void
664  push_back (const PointT& pt)
665  {
666  points.push_back (pt);
667  width = size ();
668  height = 1;
669  }
670 
671  /** \brief Insert a new point in the cloud, at the end of the container.
672  * \note This assumes the user would correct the width and height later on!
673  * \param[in] pt the point to insert
674  */
675  inline void
677  {
678  points.push_back (pt);
679  }
680 
681  /** \brief Emplace a new point in the cloud, at the end of the container.
682  * \note This breaks the organized structure of the cloud by setting the height to 1!
683  * \param[in] args the parameters to forward to the point to construct
684  * \return reference to the emplaced point
685  */
686  template <class... Args> inline reference
687  emplace_back (Args&& ...args)
688  {
689  points.emplace_back (std::forward<Args> (args)...);
690  width = size ();
691  height = 1;
692  return points.back();
693  }
694 
695  /** \brief Emplace a new point in the cloud, at the end of the container.
696  * \note This assumes the user would correct the width and height later on!
697  * \param[in] args the parameters to forward to the point to construct
698  * \return reference to the emplaced point
699  */
700  template <class... Args> inline reference
701  transient_emplace_back (Args&& ...args)
702  {
703  points.emplace_back (std::forward<Args> (args)...);
704  return points.back();
705  }
706 
707  /** \brief Insert a new point in the cloud, given an iterator.
708  * \note This breaks the organized structure of the cloud by setting the height to 1!
709  * \param[in] position where to insert the point
710  * \param[in] pt the point to insert
711  * \return returns the new position iterator
712  */
713  inline iterator
714  insert (iterator position, const PointT& pt)
715  {
716  iterator it = points.insert (std::move(position), pt);
717  width = size ();
718  height = 1;
719  return (it);
720  }
721 
722  /** \brief Insert a new point in the cloud, given an iterator.
723  * \note This assumes the user would correct the width and height later on!
724  * \param[in] position where to insert the point
725  * \param[in] pt the point to insert
726  * \return returns the new position iterator
727  */
728  inline iterator
729  transient_insert (iterator position, const PointT& pt)
730  {
731  iterator it = points.insert (std::move(position), pt);
732  return (it);
733  }
734 
735  /** \brief Insert a new point in the cloud N times, given an iterator.
736  * \note This breaks the organized structure of the cloud by setting the height to 1!
737  * \param[in] position where to insert the point
738  * \param[in] n the number of times to insert the point
739  * \param[in] pt the point to insert
740  */
741  inline void
742  insert (iterator position, std::size_t n, const PointT& pt)
743  {
744  points.insert (std::move(position), n, pt);
745  width = size ();
746  height = 1;
747  }
748 
749  /** \brief Insert a new point in the cloud N times, given an iterator.
750  * \note This assumes the user would correct the width and height later on!
751  * \param[in] position where to insert the point
752  * \param[in] n the number of times to insert the point
753  * \param[in] pt the point to insert
754  */
755  inline void
756  transient_insert (iterator position, std::size_t n, const PointT& pt)
757  {
758  points.insert (std::move(position), n, pt);
759  }
760 
761  /** \brief Insert a new range of points in the cloud, at a certain position.
762  * \note This breaks the organized structure of the cloud by setting the height to 1!
763  * \param[in] position where to insert the data
764  * \param[in] first where to start inserting the points from
765  * \param[in] last where to stop inserting the points from
766  */
767  template <class InputIterator> inline void
768  insert (iterator position, InputIterator first, InputIterator last)
769  {
770  points.insert (std::move(position), std::move(first), std::move(last));
771  width = size ();
772  height = 1;
773  }
774 
775  /** \brief Insert a new range of points in the cloud, at a certain position.
776  * \note This assumes the user would correct the width and height later on!
777  * \param[in] position where to insert the data
778  * \param[in] first where to start inserting the points from
779  * \param[in] last where to stop inserting the points from
780  */
781  template <class InputIterator> inline void
782  transient_insert (iterator position, InputIterator first, InputIterator last)
783  {
784  points.insert (std::move(position), std::move(first), std::move(last));
785  }
786 
787  /** \brief Emplace a new point in the cloud, given an iterator.
788  * \note This breaks the organized structure of the cloud by setting the height to 1!
789  * \param[in] position iterator before which the point will be emplaced
790  * \param[in] args the parameters to forward to the point to construct
791  * \return returns the new position iterator
792  */
793  template <class... Args> inline iterator
794  emplace (iterator position, Args&& ...args)
795  {
796  iterator it = points.emplace (std::move(position), std::forward<Args> (args)...);
797  width = size ();
798  height = 1;
799  return (it);
800  }
801 
802  /** \brief Emplace a new point in the cloud, given an iterator.
803  * \note This assumes the user would correct the width and height later on!
804  * \param[in] position iterator before which the point will be emplaced
805  * \param[in] args the parameters to forward to the point to construct
806  * \return returns the new position iterator
807  */
808  template <class... Args> inline iterator
809  transient_emplace (iterator position, Args&& ...args)
810  {
811  iterator it = points.emplace (std::move(position), std::forward<Args> (args)...);
812  return (it);
813  }
814 
815  /** \brief Erase a point in the cloud.
816  * \note This breaks the organized structure of the cloud by setting the height to 1!
817  * \param[in] position what data point to erase
818  * \return returns the new position iterator
819  */
820  inline iterator
821  erase (iterator position)
822  {
823  iterator it = points.erase (std::move(position));
824  width = size ();
825  height = 1;
826  return (it);
827  }
828 
829  /** \brief Erase a point in the cloud.
830  * \note This assumes the user would correct the width and height later on!
831  * \param[in] position what data point to erase
832  * \return returns the new position iterator
833  */
834  inline iterator
836  {
837  iterator it = points.erase (std::move(position));
838  return (it);
839  }
840 
841  /** \brief Erase a set of points given by a (first, last) iterator pair
842  * \note This breaks the organized structure of the cloud by setting the height to 1!
843  * \param[in] first where to start erasing points from
844  * \param[in] last where to stop erasing points from
845  * \return returns the new position iterator
846  */
847  inline iterator
848  erase (iterator first, iterator last)
849  {
850  iterator it = points.erase (std::move(first), std::move(last));
851  width = size ();
852  height = 1;
853  return (it);
854  }
855 
856  /** \brief Erase a set of points given by a (first, last) iterator pair
857  * \note This assumes the user would correct the width and height later on!
858  * \param[in] first where to start erasing points from
859  * \param[in] last where to stop erasing points from
860  * \return returns the new position iterator
861  */
862  inline iterator
864  {
865  iterator it = points.erase (std::move(first), std::move(last));
866  return (it);
867  }
868 
869  /** \brief Swap a point cloud with another cloud.
870  * \param[in,out] rhs point cloud to swap this with
871  */
872  inline void
874  {
875  std::swap (header, rhs.header);
876  this->points.swap (rhs.points);
877  std::swap (width, rhs.width);
878  std::swap (height, rhs.height);
879  std::swap (is_dense, rhs.is_dense);
880  std::swap (sensor_origin_, rhs.sensor_origin_);
881  std::swap (sensor_orientation_, rhs.sensor_orientation_);
882  }
883 
884  /** \brief Removes all points in a cloud and sets the width and height to 0. */
885  inline void
886  clear ()
887  {
888  points.clear ();
889  width = 0;
890  height = 0;
891  }
892 
893  /** \brief Copy the cloud to the heap and return a smart pointer
894  * Note that deep copy is performed, so avoid using this function on non-empty clouds.
895  * The changes of the returned cloud are not mirrored back to this one.
896  * \return shared pointer to the copy of the cloud
897  */
898  inline Ptr
899  makeShared () const { return Ptr (new PointCloud<PointT> (*this)); }
900 
902  };
903 
904 
905  template <typename PointT> std::ostream&
906  operator << (std::ostream& s, const pcl::PointCloud<PointT> &p)
907  {
908  s << "header: " << p.header << std::endl;
909  s << "points[]: " << p.size () << std::endl;
910  s << "width: " << p.width << std::endl;
911  s << "height: " << p.height << std::endl;
912  s << "is_dense: " << p.is_dense << std::endl;
913  s << "sensor origin (xyz): [" <<
914  p.sensor_origin_.x () << ", " <<
915  p.sensor_origin_.y () << ", " <<
916  p.sensor_origin_.z () << "] / orientation (xyzw): [" <<
917  p.sensor_orientation_.x () << ", " <<
918  p.sensor_orientation_.y () << ", " <<
919  p.sensor_orientation_.z () << ", " <<
920  p.sensor_orientation_.w () << "]" <<
921  std::endl;
922  return (s);
923  }
924 }
PointCloud represents the base class in PCL for storing collections of 3D points.
Definition: point_cloud.h:174
typename VectorType::size_type size_type
Definition: point_cloud.h:423
PointT * data() noexcept
Definition: point_cloud.h:448
iterator erase(iterator position)
Erase a point in the cloud.
Definition: point_cloud.h:821
const_reverse_iterator rend() const noexcept
Definition: point_cloud.h:439
void resize(uindex_t new_width, uindex_t new_height)
Resizes the container to contain new_width * new_height elements.
Definition: point_cloud.h:483
const_iterator cbegin() const noexcept
Definition: point_cloud.h:434
void push_back(const PointT &pt)
Insert a new point in the cloud, at the end of the container.
Definition: point_cloud.h:664
reference transient_emplace_back(Args &&...args)
Emplace a new point in the cloud, at the end of the container.
Definition: point_cloud.h:701
const Eigen::Map< const Eigen::MatrixXf, Eigen::Aligned, Eigen::OuterStride<> > getMatrixXfMap(int dim, int stride, int offset) const
Return an Eigen MatrixXf (assumes float values) mapped to the specified dimensions of the PointCloud.
Definition: point_cloud.h:360
const PointT & at(int column, int row) const
Obtain the point given by the (column, row) coordinates.
Definition: point_cloud.h:263
PointT & front()
Definition: point_cloud.h:537
bool empty() const
Definition: point_cloud.h:447
reverse_iterator rbegin() noexcept
Definition: point_cloud.h:436
const_iterator begin() const noexcept
Definition: point_cloud.h:432
const_iterator cend() const noexcept
Definition: point_cloud.h:435
PointT & back()
Definition: point_cloud.h:539
const PointT & operator[](std::size_t n) const
Definition: point_cloud.h:532
void insert(iterator position, std::size_t n, const PointT &pt)
Insert a new point in the cloud N times, given an iterator.
Definition: point_cloud.h:742
void transient_insert(iterator position, std::size_t n, const PointT &pt)
Insert a new point in the cloud N times, given an iterator.
Definition: point_cloud.h:756
iterator erase(iterator first, iterator last)
Erase a set of points given by a (first, last) iterator pair.
Definition: point_cloud.h:848
const_reverse_iterator crend() const noexcept
Definition: point_cloud.h:441
PointCloud & operator+=(const PointCloud &rhs)
Add a point cloud to the current cloud.
Definition: point_cloud.h:215
Eigen::Map< Eigen::MatrixXf, Eigen::Aligned, Eigen::OuterStride<> > getMatrixXfMap()
Definition: point_cloud.h:375
PointCloud(std::uint32_t width_, std::uint32_t height_, const PointT &value_=PointT())
Allocate constructor from point cloud subset.
Definition: point_cloud.h:202
void resize(index_t count, const PointT &value)
Resizes the container to contain count elements.
Definition: point_cloud.h:503
PointT & at(std::size_t n)
Definition: point_cloud.h:535
const_reverse_iterator crbegin() const noexcept
Definition: point_cloud.h:440
bool is_dense
True if no points are invalid (e.g., have NaN or Inf values in any of their floating point fields).
Definition: point_cloud.h:404
void insert(iterator position, InputIterator first, InputIterator last)
Insert a new range of points in the cloud, at a certain position.
Definition: point_cloud.h:768
iterator transient_erase(iterator first, iterator last)
Erase a set of points given by a (first, last) iterator pair.
Definition: point_cloud.h:863
PointCloud operator+(const PointCloud &rhs)
Add a point cloud to another cloud.
Definition: point_cloud.h:226
typename VectorType::reverse_iterator reverse_iterator
Definition: point_cloud.h:428
const PointT & at(std::size_t n) const
Definition: point_cloud.h:534
const PointT & front() const
Definition: point_cloud.h:536
iterator transient_erase(iterator position)
Erase a point in the cloud.
Definition: point_cloud.h:835
void resize(std::size_t count)
Resizes the container to contain count elements.
Definition: point_cloud.h:463
void assign(InputIterator first, InputIterator last, index_t new_width)
Replaces the points with copies of those in the range [first, last)
Definition: point_cloud.h:597
typename VectorType::iterator iterator
Definition: point_cloud.h:426
Eigen::Quaternionf sensor_orientation_
Sensor acquisition pose (rotation).
Definition: point_cloud.h:409
void transient_push_back(const PointT &pt)
Insert a new point in the cloud, at the end of the container.
Definition: point_cloud.h:676
const PointT & back() const
Definition: point_cloud.h:538
std::uint32_t width
The point cloud width (if organized as an image-structure).
Definition: point_cloud.h:399
PointT & reference
Definition: point_cloud.h:420
void assign(std::initializer_list< PointT > ilist)
Replaces the points with the elements from the initializer list ilist
Definition: point_cloud.h:624
reference emplace_back(Args &&...args)
Emplace a new point in the cloud, at the end of the container.
Definition: point_cloud.h:687
iterator insert(iterator position, const PointT &pt)
Insert a new point in the cloud, given an iterator.
Definition: point_cloud.h:714
PointCloud(const PointCloud< PointT > &pc, const Indices &indices)
Copy constructor from point cloud subset.
Definition: point_cloud.h:186
PointCloud()=default
Default constructor.
pcl::PCLHeader header
The point cloud header.
Definition: point_cloud.h:393
std::vector< PointCloud< PointT >, Eigen::aligned_allocator< PointCloud< PointT > > > CloudVectorType
Definition: point_cloud.h:413
iterator emplace(iterator position, Args &&...args)
Emplace a new point in the cloud, given an iterator.
Definition: point_cloud.h:794
static bool concatenate(const pcl::PointCloud< PointT > &cloud1, const pcl::PointCloud< PointT > &cloud2, pcl::PointCloud< PointT > &cloud_out)
Definition: point_cloud.h:249
void assign(InputIterator first, InputIterator last)
Replaces the points with copies of those in the range [first, last)
Definition: point_cloud.h:579
typename VectorType::const_iterator const_iterator
Definition: point_cloud.h:427
iterator end() noexcept
Definition: point_cloud.h:431
bool isOrganized() const
Return whether a dataset is organized (e.g., arranged in a structured grid).
Definition: point_cloud.h:311
std::uint32_t height
The point cloud height (if organized as an image-structure).
Definition: point_cloud.h:401
PointT & at(int column, int row)
Obtain the point given by the (column, row) coordinates.
Definition: point_cloud.h:277
void clear()
Removes all points in a cloud and sets the width and height to 0.
Definition: point_cloud.h:886
void resize(index_t new_width, index_t new_height, const PointT &value)
Resizes the container to contain count elements.
Definition: point_cloud.h:524
void transient_insert(iterator position, InputIterator first, InputIterator last)
Insert a new range of points in the cloud, at a certain position.
Definition: point_cloud.h:782
typename VectorType::const_reverse_iterator const_reverse_iterator
Definition: point_cloud.h:429
std::size_t size() const
Definition: point_cloud.h:444
void assign(std::initializer_list< PointT > ilist, index_t new_width)
Replaces the points with the elements from the initializer list ilist
Definition: point_cloud.h:639
Eigen::Vector4f sensor_origin_
Sensor acquisition pose (origin/translation).
Definition: point_cloud.h:407
void reserve(std::size_t n)
Definition: point_cloud.h:446
const PointT & operator()(std::size_t column, std::size_t row) const
Obtain the point given by the (column, row) coordinates.
Definition: point_cloud.h:291
std::vector< PointT, Eigen::aligned_allocator< PointT > > VectorType
Definition: point_cloud.h:412
void swap(PointCloud< PointT > &rhs)
Swap a point cloud with another cloud.
Definition: point_cloud.h:873
shared_ptr< PointCloud< PointT > > Ptr
Definition: point_cloud.h:414
Eigen::Map< Eigen::MatrixXf, Eigen::Aligned, Eigen::OuterStride<> > getMatrixXfMap(int dim, int stride, int offset)
Return an Eigen MatrixXf (assumes float values) mapped to the specified dimensions of the PointCloud.
Definition: point_cloud.h:334
typename VectorType::difference_type difference_type
Definition: point_cloud.h:422
index_t max_size() const noexcept
Definition: point_cloud.h:445
const_iterator end() const noexcept
Definition: point_cloud.h:433
iterator begin() noexcept
Definition: point_cloud.h:430
void assign(index_t count, const PointT &value)
Replaces the points with count copies of value
Definition: point_cloud.h:549
const Eigen::Map< const Eigen::MatrixXf, Eigen::Aligned, Eigen::OuterStride<> > getMatrixXfMap() const
Definition: point_cloud.h:387
const_reverse_iterator rbegin() const noexcept
Definition: point_cloud.h:438
void assign(index_t new_width, index_t new_height, const PointT &value)
Replaces the points with new_width * new_height copies of value
Definition: point_cloud.h:563
iterator transient_insert(iterator position, const PointT &pt)
Insert a new point in the cloud, given an iterator.
Definition: point_cloud.h:729
iterator transient_emplace(iterator position, Args &&...args)
Emplace a new point in the cloud, given an iterator.
Definition: point_cloud.h:809
static bool concatenate(pcl::PointCloud< PointT > &cloud1, const pcl::PointCloud< PointT > &cloud2)
Definition: point_cloud.h:232
std::vector< PointT, Eigen::aligned_allocator< PointT > > points
The point data.
Definition: point_cloud.h:396
reverse_iterator rend() noexcept
Definition: point_cloud.h:437
shared_ptr< const PointCloud< PointT > > ConstPtr
Definition: point_cloud.h:415
const PointT * data() const noexcept
Definition: point_cloud.h:449
Ptr makeShared() const
Copy the cloud to the heap and return a smart pointer Note that deep copy is performed,...
Definition: point_cloud.h:899
An exception that is thrown when an organized point cloud is needed but not provided.
Definition: exceptions.h:211
#define PCL_MAKE_ALIGNED_OPERATOR_NEW
Macro to signal a class requires a custom allocator.
Definition: memory.h:86
Defines functions, macros and traits for allocating and using memory.
detail::int_type_t< detail::index_type_size, false > uindex_t
Type used for an unsigned index in PCL.
Definition: types.h:120
detail::int_type_t< detail::index_type_size, detail::index_type_signed > index_t
Type used for an index in PCL.
Definition: types.h:112
std::ostream & operator<<(std::ostream &os, const BivariatePolynomialT< real > &p)
IndicesAllocator<> Indices
Type used for indices in PCL.
Definition: types.h:133
std::vector< detail::FieldMapping > MsgFieldMap
Definition: point_cloud.h:73
Defines all the PCL and non-PCL macros used.
Helper functor structure for copying data between an Eigen type and a PointT.
Definition: point_cloud.h:78
NdCopyEigenPointFunctor(const Eigen::VectorXf &p1, PointOutT &p2)
Constructor.
Definition: point_cloud.h:85
typename traits::POD< PointOutT >::type Pod
Definition: point_cloud.h:79
void operator()()
Operator.
Definition: point_cloud.h:92
Helper functor structure for copying data between an Eigen type and a PointT.
Definition: point_cloud.h:111
typename traits::POD< PointInT >::type Pod
Definition: point_cloud.h:112
void operator()()
Operator.
Definition: point_cloud.h:123
NdCopyPointEigenFunctor(const PointInT &p1, Eigen::VectorXf &p2)
Constructor.
Definition: point_cloud.h:118
std::uint64_t stamp
A timestamp associated with the time when the data was acquired.
Definition: PCLHeader.h:18
A point structure representing Euclidean xyz coordinates, and the RGB color.
std::size_t serialized_offset
Definition: point_cloud.h:65
Defines basic non-point types used by PCL.