Point Cloud Library (PCL) 1.13.0
io.h
1/*
2 * Software License Agreement (BSD License)
3 *
4 * Point Cloud Library (PCL) - www.pointclouds.org
5 * Copyright (c) 2010-2011, 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 * $Id$
38 *
39 */
40
41#pragma once
42
43#include <numeric>
44#include <string>
45
46#include <pcl/point_cloud.h>
47#include <pcl/PointIndices.h>
48#include <pcl/pcl_macros.h>
49#include <pcl/PolygonMesh.h>
50#include <locale>
51
52namespace pcl
53{
54 /** \brief Get the index of a specified field (i.e., dimension/channel)
55 * \param[in] cloud the point cloud message
56 * \param[in] field_name the string defining the field name
57 * \ingroup common
58 */
59 inline int
60 getFieldIndex (const pcl::PCLPointCloud2 &cloud, const std::string &field_name)
61 {
62 // Get the index we need
63 const auto result = std::find_if(cloud.fields.begin (), cloud.fields.end (),
64 [&field_name](const auto field) { return field.name == field_name; });
65 if (result == cloud.fields.end ())
66 return -1;
67 return std::distance(cloud.fields.begin (), result);
68 }
69
70 /** \brief Get the index of a specified field (i.e., dimension/channel)
71 * \tparam PointT datatype for which fields is being queries
72 * \param[in] field_name the string defining the field name
73 * \param[out] fields a vector to the original \a PCLPointField vector that the raw PointCloud message contains
74 * \ingroup common
75 */
76 template <typename PointT> inline int
77 getFieldIndex (const std::string &field_name,
78 std::vector<pcl::PCLPointField> &fields);
79 /** \brief Get the index of a specified field (i.e., dimension/channel)
80 * \tparam PointT datatype for which fields is being queries
81 * \param[in] field_name the string defining the field name
82 * \param[in] fields a vector to the original \a PCLPointField vector that the raw PointCloud message contains
83 * \ingroup common
84 */
85 template <typename PointT> inline int
86 getFieldIndex (const std::string &field_name,
87 const std::vector<pcl::PCLPointField> &fields);
88
89 /** \brief Get the list of available fields (i.e., dimension/channel)
90 * \tparam PointT datatype whose details are requested
91 * \ingroup common
92 */
93 template <typename PointT> inline std::vector<pcl::PCLPointField>
94 getFields ();
95
96 /** \brief Get the list of all fields available in a given cloud
97 * \param[in] cloud the point cloud message
98 * \ingroup common
99 */
100 template <typename PointT> inline std::string
102
103 /** \brief Get the available point cloud fields as a space separated string
104 * \param[in] cloud a pointer to the PointCloud message
105 * \ingroup common
106 */
107 inline std::string
109 {
110 return std::accumulate(std::next (cloud.fields.begin ()), cloud.fields.end (), cloud.fields[0].name,
111 [](const auto& acc, const auto& field) { return acc + " " + field.name; });
112 }
113
114 /** \brief Obtains the size of a specific field data type in bytes
115 * \param[in] datatype the field data type (see PCLPointField.h)
116 * \ingroup common
117 */
118 inline int
119 getFieldSize (const int datatype)
120 {
121 switch (datatype)
122 {
124 return sizeof(bool);
125
128 return (1);
129
132 return (2);
133
137 return (4);
138
142 return (8);
143
144 default:
145 return (0);
146 }
147 }
148
149 /** \brief Obtain a vector with the sizes of all valid fields (e.g., not "_")
150 * \param[in] fields the input vector containing the fields
151 * \param[out] field_sizes the resultant field sizes in bytes
152 */
153 PCL_EXPORTS void
154 getFieldsSizes (const std::vector<pcl::PCLPointField> &fields,
155 std::vector<int> &field_sizes);
156
157 /** \brief Obtains the type of the PCLPointField from a specific size and type
158 * \param[in] size the size in bytes of the data field
159 * \param[in] type a char describing the type of the field ('B' = bool, 'F' = float, 'I' = signed, 'U' = unsigned)
160 * \ingroup common
161 */
162 inline int
163 getFieldType (const int size, char type)
164 {
165 type = std::toupper (type, std::locale::classic ());
166
167 // extra logic for bool because its size is undefined
168 if (type == 'B') {
169 if (size == sizeof(bool)) {
171 } else {
172 return -1;
173 }
174 }
175
176 switch (size)
177 {
178 case 1:
179 if (type == 'I')
181 if (type == 'U')
183 break;
184
185 case 2:
186 if (type == 'I')
188 if (type == 'U')
190 break;
191
192 case 4:
193 if (type == 'I')
195 if (type == 'U')
197 if (type == 'F')
199 break;
200
201 case 8:
202 if (type == 'I')
204 if (type == 'U')
206 if (type == 'F')
208 break;
209 }
210 return (-1);
211 }
212
213 /** \brief Obtains the type of the PCLPointField from a specific PCLPointField as a char
214 * \param[in] type the PCLPointField field type
215 * \ingroup common
216 */
217 inline char
218 getFieldType (const int type)
219 {
220 switch (type)
221 {
223 return ('B');
224
229 return ('I');
230
235 return ('U');
236
239 return ('F');
240
241 default:
242 return ('?');
243 }
244 }
245
247 {
252 };
253
254 /** \brief \return the right index according to the interpolation type.
255 * \note this is adapted from OpenCV
256 * \param p the index of point to interpolate
257 * \param length the top/bottom row or left/right column index
258 * \param type the requested interpolation
259 * \throws pcl::BadArgumentException if type is unknown
260 */
261 PCL_EXPORTS int
262 interpolatePointIndex (int p, int length, InterpolationType type);
263
264 /** \brief Concatenate two pcl::PointCloud<PointT>
265 * \param[in] cloud1 the first input point cloud dataset
266 * \param[in] cloud2 the second input point cloud dataset
267 * \param[out] cloud_out the resultant output point cloud dataset
268 * \return true if successful, false otherwise
269 * \ingroup common
270 */
271 template <typename PointT>
272 PCL_EXPORTS bool
274 const pcl::PointCloud<PointT> &cloud2,
275 pcl::PointCloud<PointT> &cloud_out)
276 {
277 return pcl::PointCloud<PointT>::concatenate(cloud1, cloud2, cloud_out);
278 }
279
280 /** \brief Concatenate two pcl::PCLPointCloud2
281 *
282 * \warning This function will concatenate IFF the non-skip fields are in the correct
283 * order and same in number.
284 * \param[in] cloud1 the first input point cloud dataset
285 * \param[in] cloud2 the second input point cloud dataset
286 * \param[out] cloud_out the resultant output point cloud dataset
287 * \return true if successful, false otherwise
288 * \ingroup common
289 */
290 PCL_EXPORTS inline bool
292 const pcl::PCLPointCloud2 &cloud2,
293 pcl::PCLPointCloud2 &cloud_out)
294 {
295 return pcl::PCLPointCloud2::concatenate(cloud1, cloud2, cloud_out);
296 }
297
298 /** \brief Concatenate two pcl::PolygonMesh
299 * \param[in] mesh1 the first input mesh
300 * \param[in] mesh2 the second input mesh
301 * \param[out] mesh_out the resultant output mesh
302 * \return true if successful, false otherwise
303 * \ingroup common
304 */
305 PCL_EXPORTS inline bool
307 const pcl::PolygonMesh &mesh2,
308 pcl::PolygonMesh &mesh_out)
309 {
310 return pcl::PolygonMesh::concatenate(mesh1, mesh2, mesh_out);
311 }
312
313 /** \brief Extract the indices of a given point cloud as a new point cloud
314 * \param[in] cloud_in the input point cloud dataset
315 * \param[in] indices the vector of indices representing the points to be copied from \a cloud_in
316 * \param[out] cloud_out the resultant output point cloud dataset
317 * \note Assumes unique indices.
318 * \ingroup common
319 */
320 PCL_EXPORTS void
322 const Indices &indices,
323 pcl::PCLPointCloud2 &cloud_out);
324
325 /** \brief Extract the indices of a given point cloud as a new point cloud
326 * \param[in] cloud_in the input point cloud dataset
327 * \param[in] indices the vector of indices representing the points to be copied from \a cloud_in
328 * \param[out] cloud_out the resultant output point cloud dataset
329 * \note Assumes unique indices.
330 * \ingroup common
331 */
332 PCL_EXPORTS void
334 const IndicesAllocator< Eigen::aligned_allocator<index_t> > &indices,
335 pcl::PCLPointCloud2 &cloud_out);
336
337 /** \brief Copy fields and point cloud data from \a cloud_in to \a cloud_out
338 * \param[in] cloud_in the input point cloud dataset
339 * \param[out] cloud_out the resultant output point cloud dataset
340 * \ingroup common
341 */
342 PCL_EXPORTS void
344 pcl::PCLPointCloud2 &cloud_out);
345
346 /** \brief Check if two given point types are the same or not. */
347template <typename Point1T, typename Point2T> constexpr bool
349 {
350 return (std::is_same<remove_cvref_t<Point1T>, remove_cvref_t<Point2T>>::value);
351 }
352
353 /** \brief Extract the indices of a given point cloud as a new point cloud
354 * \param[in] cloud_in the input point cloud dataset
355 * \param[in] indices the vector of indices representing the points to be copied from \a cloud_in
356 * \param[out] cloud_out the resultant output point cloud dataset
357 * \note Assumes unique indices.
358 * \ingroup common
359 */
360 template <typename PointT, typename IndicesVectorAllocator = std::allocator<index_t>> void
362 const IndicesAllocator< IndicesVectorAllocator> &indices,
363 pcl::PointCloud<PointT> &cloud_out);
364
365 /** \brief Extract the indices of a given point cloud as a new point cloud
366 * \param[in] cloud_in the input point cloud dataset
367 * \param[in] indices the PointIndices structure representing the points to be copied from cloud_in
368 * \param[out] cloud_out the resultant output point cloud dataset
369 * \note Assumes unique indices.
370 * \ingroup common
371 */
372 template <typename PointT> void
374 const PointIndices &indices,
375 pcl::PointCloud<PointT> &cloud_out);
376
377 /** \brief Extract the indices of a given point cloud as a new point cloud
378 * \param[in] cloud_in the input point cloud dataset
379 * \param[in] indices the vector of indices representing the points to be copied from \a cloud_in
380 * \param[out] cloud_out the resultant output point cloud dataset
381 * \note Assumes unique indices.
382 * \ingroup common
383 */
384 template <typename PointT> void
386 const std::vector<pcl::PointIndices> &indices,
387 pcl::PointCloud<PointT> &cloud_out);
388
389 /** \brief Copy all the fields from a given point cloud into a new point cloud
390 * \param[in] cloud_in the input point cloud dataset
391 * \param[out] cloud_out the resultant output point cloud dataset
392 * \ingroup common
393 */
394 template <typename PointInT, typename PointOutT> void
396 pcl::PointCloud<PointOutT> &cloud_out);
397
398 /** \brief Extract the indices of a given point cloud as a new point cloud
399 * \param[in] cloud_in the input point cloud dataset
400 * \param[in] indices the vector of indices representing the points to be copied from \a cloud_in
401 * \param[out] cloud_out the resultant output point cloud dataset
402 * \note Assumes unique indices.
403 * \ingroup common
404 */
405 template <typename PointInT, typename PointOutT, typename IndicesVectorAllocator = std::allocator<index_t>> void
407 const IndicesAllocator<IndicesVectorAllocator> &indices,
408 pcl::PointCloud<PointOutT> &cloud_out);
409
410 /** \brief Extract the indices of a given point cloud as a new point cloud
411 * \param[in] cloud_in the input point cloud dataset
412 * \param[in] indices the PointIndices structure representing the points to be copied from cloud_in
413 * \param[out] cloud_out the resultant output point cloud dataset
414 * \note Assumes unique indices.
415 * \ingroup common
416 */
417 template <typename PointInT, typename PointOutT> void
419 const PointIndices &indices,
420 pcl::PointCloud<PointOutT> &cloud_out);
421
422 /** \brief Extract the indices of a given point cloud as a new point cloud
423 * \param[in] cloud_in the input point cloud dataset
424 * \param[in] indices the vector of indices representing the points to be copied from cloud_in
425 * \param[out] cloud_out the resultant output point cloud dataset
426 * \note Assumes unique indices.
427 * \ingroup common
428 */
429 template <typename PointInT, typename PointOutT> void
431 const std::vector<pcl::PointIndices> &indices,
432 pcl::PointCloud<PointOutT> &cloud_out);
433
434 /** \brief Copy a point cloud inside a larger one interpolating borders.
435 * \param[in] cloud_in the input point cloud dataset
436 * \param[out] cloud_out the resultant output point cloud dataset
437 * \param top
438 * \param bottom
439 * \param left
440 * \param right
441 * Position of cloud_in inside cloud_out is given by \a top, \a left, \a bottom \a right.
442 * \param[in] border_type the interpolating method (pcl::BORDER_XXX)
443 * BORDER_REPLICATE: aaaaaa|abcdefgh|hhhhhhh
444 * BORDER_REFLECT: fedcba|abcdefgh|hgfedcb
445 * BORDER_REFLECT_101: gfedcb|abcdefgh|gfedcba
446 * BORDER_WRAP: cdefgh|abcdefgh|abcdefg
447 * BORDER_CONSTANT: iiiiii|abcdefgh|iiiiiii with some specified 'i'
448 * BORDER_TRANSPARENT: mnopqr|abcdefgh|tuvwxyz where m-r and t-z are original values of cloud_out
449 * \param value
450 * \throw pcl::BadArgumentException if any of top, bottom, left or right is negative.
451 * \ingroup common
452 */
453 template <typename PointT> void
455 pcl::PointCloud<PointT> &cloud_out,
456 int top, int bottom, int left, int right,
457 pcl::InterpolationType border_type, const PointT& value);
458
459 /** \brief Concatenate two datasets representing different fields.
460 *
461 * \note If the input datasets have overlapping fields (i.e., both contain
462 * the same fields), then the data in the second cloud (cloud2_in) will
463 * overwrite the data in the first (cloud1_in).
464 *
465 * \param[in] cloud1_in the first input dataset
466 * \param[in] cloud2_in the second input dataset (overwrites the fields of the first dataset for those that are shared)
467 * \param[out] cloud_out the resultant output dataset created by the concatenation of all the fields in the input datasets
468 * \ingroup common
469 */
470 template <typename PointIn1T, typename PointIn2T, typename PointOutT> void
472 const pcl::PointCloud<PointIn2T> &cloud2_in,
473 pcl::PointCloud<PointOutT> &cloud_out);
474
475 /** \brief Concatenate two datasets representing different fields.
476 *
477 * \note If the input datasets have overlapping fields (i.e., both contain
478 * the same fields), then the data in the second cloud (cloud2_in) will
479 * overwrite the data in the first (cloud1_in).
480 *
481 * \param[in] cloud1_in the first input dataset
482 * \param[in] cloud2_in the second input dataset (overwrites the fields of the first dataset for those that are shared)
483 * \param[out] cloud_out the output dataset created by concatenating all the fields in the input datasets
484 * \ingroup common
485 */
486 PCL_EXPORTS bool
488 const pcl::PCLPointCloud2 &cloud2_in,
489 pcl::PCLPointCloud2 &cloud_out);
490
491 /** \brief Copy the XYZ dimensions of a pcl::PCLPointCloud2 into Eigen format
492 * \param[in] in the point cloud message
493 * \param[out] out the resultant Eigen MatrixXf format containing XYZ0 / point
494 * \ingroup common
495 */
496 PCL_EXPORTS bool
497 getPointCloudAsEigen (const pcl::PCLPointCloud2 &in, Eigen::MatrixXf &out);
498
499 /** \brief Copy the XYZ dimensions from an Eigen MatrixXf into a pcl::PCLPointCloud2 message
500 * \param[in] in the Eigen MatrixXf format containing XYZ0 / point
501 * \param[out] out the resultant point cloud message
502 * \note the method assumes that the PCLPointCloud2 message already has the fields set up properly !
503 * \ingroup common
504 */
505 PCL_EXPORTS bool
506 getEigenAsPointCloud (Eigen::MatrixXf &in, pcl::PCLPointCloud2 &out);
507
508 namespace io
509 {
510 /** \brief swap bytes order of a char array of length N
511 * \param bytes char array to swap
512 * \ingroup common
513 */
514 template <std::size_t N> void
515 swapByte (char* bytes);
516
517 /** \brief specialization of swapByte for dimension 1
518 * \param bytes char array to swap
519 */
520 template <> inline void
521 swapByte<1> (char* bytes) { bytes[0] = bytes[0]; }
522
523
524 /** \brief specialization of swapByte for dimension 2
525 * \param bytes char array to swap
526 */
527 template <> inline void
528 swapByte<2> (char* bytes) { std::swap (bytes[0], bytes[1]); }
529
530 /** \brief specialization of swapByte for dimension 4
531 * \param bytes char array to swap
532 */
533 template <> inline void
534 swapByte<4> (char* bytes)
535 {
536 std::swap (bytes[0], bytes[3]);
537 std::swap (bytes[1], bytes[2]);
538 }
539
540 /** \brief specialization of swapByte for dimension 8
541 * \param bytes char array to swap
542 */
543 template <> inline void
544 swapByte<8> (char* bytes)
545 {
546 std::swap (bytes[0], bytes[7]);
547 std::swap (bytes[1], bytes[6]);
548 std::swap (bytes[2], bytes[5]);
549 std::swap (bytes[3], bytes[4]);
550 }
551
552 /** \brief swaps byte of an arbitrary type T casting it to char*
553 * \param value the data you want its bytes swapped
554 */
555 template <typename T> void
556 swapByte (T& value)
557 {
558 pcl::io::swapByte<sizeof(T)> (reinterpret_cast<char*> (&value));
559 }
560 }
561}
562
563#include <pcl/common/impl/io.hpp>
PointCloud represents the base class in PCL for storing collections of 3D points.
Definition: point_cloud.h:173
static bool concatenate(pcl::PointCloud< PointT > &cloud1, const pcl::PointCloud< PointT > &cloud2)
Definition: point_cloud.h:231
void swapByte(char *bytes)
swap bytes order of a char array of length N
PCL_EXPORTS bool getPointCloudAsEigen(const pcl::PCLPointCloud2 &in, Eigen::MatrixXf &out)
Copy the XYZ dimensions of a pcl::PCLPointCloud2 into Eigen format.
PCL_EXPORTS bool getEigenAsPointCloud(Eigen::MatrixXf &in, pcl::PCLPointCloud2 &out)
Copy the XYZ dimensions from an Eigen MatrixXf into a pcl::PCLPointCloud2 message.
int getFieldSize(const int datatype)
Obtains the size of a specific field data type in bytes.
Definition: io.h:119
std::string getFieldsList(const pcl::PointCloud< PointT > &)
Get the list of all fields available in a given cloud.
Definition: io.hpp:107
int getFieldType(const int size, char type)
Obtains the type of the PCLPointField from a specific size and type.
Definition: io.h:163
void concatenateFields(const pcl::PointCloud< PointIn1T > &cloud1_in, const pcl::PointCloud< PointIn2T > &cloud2_in, pcl::PointCloud< PointOutT > &cloud_out)
Concatenate two datasets representing different fields.
Definition: io.hpp:303
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:273
#define PCL_FALLTHROUGH
Macro to add a no-op or a fallthrough attribute based on compiler feature.
Definition: pcl_macros.h:433
void copyPointCloud(const pcl::PointCloud< PointInT > &cloud_in, pcl::PointCloud< PointOutT > &cloud_out)
Copy all the fields from a given point cloud into a new point cloud.
Definition: io.hpp:142
float distance(const PointT &p1, const PointT &p2)
Definition: geometry.h:60
void swapByte< 1 >(char *bytes)
specialization of swapByte for dimension 1
Definition: io.h:521
void swapByte< 4 >(char *bytes)
specialization of swapByte for dimension 4
Definition: io.h:534
void swapByte< 2 >(char *bytes)
specialization of swapByte for dimension 2
Definition: io.h:528
void swapByte< 8 >(char *bytes)
specialization of swapByte for dimension 8
Definition: io.h:544
int getFieldIndex(const pcl::PointCloud< PointT > &, const std::string &field_name, std::vector< pcl::PCLPointField > &fields)
Definition: io.hpp:52
InterpolationType
Definition: io.h:247
@ BORDER_REFLECT
Definition: io.h:249
@ BORDER_REFLECT_101
Definition: io.h:250
@ BORDER_TRANSPARENT
Definition: io.h:250
@ BORDER_DEFAULT
Definition: io.h:251
@ BORDER_CONSTANT
Definition: io.h:248
@ BORDER_WRAP
Definition: io.h:249
@ BORDER_REPLICATE
Definition: io.h:248
PCL_EXPORTS int interpolatePointIndex(int p, int length, InterpolationType type)
constexpr bool isSamePointType() noexcept
Check if two given point types are the same or not.
Definition: io.h:348
std::vector< index_t, Allocator > IndicesAllocator
Type used for indices in PCL.
Definition: types.h:128
std::remove_cv_t< std::remove_reference_t< T > > remove_cvref_t
Definition: type_traits.h:298
IndicesAllocator<> Indices
Type used for indices in PCL.
Definition: types.h:133
PCL_EXPORTS void getFieldsSizes(const std::vector< pcl::PCLPointField > &fields, std::vector< int > &field_sizes)
Obtain a vector with the sizes of all valid fields (e.g., not "_")
void getFields(const pcl::PointCloud< PointT > &, std::vector< pcl::PCLPointField > &fields)
Definition: io.hpp:83
Defines all the PCL and non-PCL macros used.
#define PCL_EXPORTS
Definition: pcl_macros.h:323
std::vector<::pcl::PCLPointField > fields
static bool concatenate(pcl::PCLPointCloud2 &cloud1, const pcl::PCLPointCloud2 &cloud2)
Inplace concatenate two pcl::PCLPointCloud2.
A point structure representing Euclidean xyz coordinates, and the RGB color.
static bool concatenate(pcl::PolygonMesh &mesh1, const pcl::PolygonMesh &mesh2)
Inplace concatenate two pcl::PolygonMesh.
Definition: PolygonMesh.h:30