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