Point Cloud Library (PCL) 1.15.1
Loading...
Searching...
No Matches
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
59namespace pcl
60{
61 namespace detail
62 {
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<> >
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
419 using value_type = PointT;
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
676 transient_push_back (const PointT& pt)
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_);
882 }
883
884 /** \brief Removes all points in a cloud and sets the width and height to 0. */
885 inline void
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.
typename VectorType::size_type size_type
iterator erase(iterator position)
Erase a point in the cloud.
const_reverse_iterator rend() const noexcept
void resize(uindex_t new_width, uindex_t new_height)
Resizes the container to contain new_width * new_height elements.
const_iterator cbegin() const noexcept
void push_back(const PointT &pt)
Insert a new point in the cloud, at the end of the container.
reference transient_emplace_back(Args &&...args)
Emplace a new point in the cloud, at the end of the container.
bool empty() const
reverse_iterator rbegin() noexcept
const_iterator begin() const noexcept
const_iterator cend() const noexcept
void insert(iterator position, std::size_t n, const PointT &pt)
Insert a new point in the cloud N times, given an iterator.
void transient_insert(iterator position, std::size_t n, const PointT &pt)
Insert a new point in the cloud N times, given an iterator.
iterator erase(iterator first, iterator last)
Erase a set of points given by a (first, last) iterator pair.
const_reverse_iterator crend() const noexcept
const PointT & back() const
Eigen::Map< Eigen::MatrixXf, Eigen::Aligned, Eigen::OuterStride<> > getMatrixXfMap()
PointCloud(std::uint32_t width_, std::uint32_t height_, const PointT &value_=PointT())
Allocate constructor from point cloud subset.
void resize(index_t count, const PointT &value)
Resizes the container to contain count elements.
const_reverse_iterator crbegin() const noexcept
void insert(iterator position, InputIterator first, InputIterator last)
Insert a new range of points in the cloud, at a certain position.
iterator transient_erase(iterator first, iterator last)
Erase a set of points given by a (first, last) iterator pair.
PointT & at(int column, int row)
Obtain the point given by the (column, row) coordinates.
PointCloud operator+(const PointCloud &rhs)
Add a point cloud to another cloud.
typename VectorType::reverse_iterator reverse_iterator
const PointT & front() const
PointCloud & operator+=(const PointCloud &rhs)
Add a point cloud to the current cloud.
iterator transient_erase(iterator position)
Erase a point in the cloud.
void resize(std::size_t count)
Resizes the container to contain count elements.
void assign(InputIterator first, InputIterator last, index_t new_width)
Replaces the points with copies of those in the range [first, last).
PointT & front()
typename VectorType::iterator iterator
PointT * data() noexcept
Eigen::Quaternionf sensor_orientation_
const PointT & at(int column, int row) const
Obtain the point given by the (column, row) coordinates.
const PointT & operator[](std::size_t n) const
void transient_push_back(const PointT &pt)
Insert a new point in the cloud, at the end of the container.
void assign(std::initializer_list< PointT > ilist)
Replaces the points with the elements from the initializer list ilist.
reference emplace_back(Args &&...args)
Emplace a new point in the cloud, at the end of the container.
iterator insert(iterator position, const PointT &pt)
Insert a new point in the cloud, given an iterator.
PointT & at(std::size_t n)
PointCloud(const PointCloud< PointT > &pc, const Indices &indices)
Copy constructor from point cloud subset.
PointCloud()=default
Default constructor.
const Eigen::Map< const Eigen::MatrixXf, Eigen::Aligned, Eigen::OuterStride<> > getMatrixXfMap() const
PointT & back()
const PointT & operator()(std::size_t column, std::size_t row) const
Obtain the point given by the (column, row) coordinates.
std::vector< PointCloud< PointInT >, Eigen::aligned_allocator< PointCloud< PointInT > > > CloudVectorType
iterator emplace(iterator position, Args &&...args)
Emplace a new point in the cloud, given an iterator.
static bool concatenate(const pcl::PointCloud< PointT > &cloud1, const pcl::PointCloud< PointT > &cloud2, pcl::PointCloud< PointT > &cloud_out)
void assign(InputIterator first, InputIterator last)
Replaces the points with copies of those in the range [first, last).
typename VectorType::const_iterator const_iterator
iterator end() noexcept
bool isOrganized() const
Return whether a dataset is organized (e.g., arranged in a structured grid).
void clear()
Removes all points in a cloud and sets the width and height to 0.
void resize(index_t new_width, index_t new_height, const PointT &value)
Resizes the container to contain count elements.
void transient_insert(iterator position, InputIterator first, InputIterator last)
Insert a new range of points in the cloud, at a certain position.
typename VectorType::const_reverse_iterator const_reverse_iterator
const PointInT & const_reference
std::size_t size() const
const PointT * data() const noexcept
void assign(std::initializer_list< PointT > ilist, index_t new_width)
Replaces the points with the elements from the initializer list ilist.
Eigen::Vector4f sensor_origin_
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.
void reserve(std::size_t n)
std::vector< PointInT, Eigen::aligned_allocator< PointInT > > VectorType
void swap(PointCloud< PointT > &rhs)
Swap a point cloud with another cloud.
shared_ptr< PointCloud< PointInT > > Ptr
typename VectorType::difference_type difference_type
index_t max_size() const noexcept
const_iterator end() const noexcept
iterator begin() noexcept
void assign(index_t count, const PointT &value)
Replaces the points with count copies of value.
const_reverse_iterator rbegin() const noexcept
void assign(index_t new_width, index_t new_height, const PointT &value)
Replaces the points with new_width * new_height copies of value.
iterator transient_insert(iterator position, const PointT &pt)
Insert a new point in the cloud, given an iterator.
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.
iterator transient_emplace(iterator position, Args &&...args)
Emplace a new point in the cloud, given an iterator.
static bool concatenate(pcl::PointCloud< PointT > &cloud1, const pcl::PointCloud< PointT > &cloud2)
std::vector< PointInT, Eigen::aligned_allocator< PointInT > > points
reverse_iterator rend() noexcept
shared_ptr< const PointCloud< PointInT > > ConstPtr
const PointT & at(std::size_t n) const
Ptr makeShared() const
Copy the cloud to the heap and return a smart pointer Note that deep copy is performed,...
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, 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
detail::int_type_t< detail::index_type_size, false > uindex_t
Type used for an unsigned index in PCL.
Definition types.h:120
Defines all the PCL and non-PCL macros used.
NdCopyEigenPointFunctor(const Eigen::VectorXf &p1, PointOutT &p2)
Constructor.
Definition point_cloud.h:85
typename traits::POD< PointOutT >::type Pod
Definition point_cloud.h:79
typename traits::POD< PointInT >::type Pod
NdCopyPointEigenFunctor(const PointInT &p1, Eigen::VectorXf &p2)
Constructor.
std::uint64_t stamp
A timestamp associated with the time when the data was acquired.
Definition PCLHeader.h:18
std::size_t serialized_offset
Definition point_cloud.h:65
Defines basic non-point types used by PCL.