Point Cloud Library (PCL) 1.15.1-dev
Loading...
Searching...
No Matches
io.hpp
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 <pcl/conversions.h> // for FieldAdder
44#include <pcl/common/concatenate.h>
45#include <pcl/common/copy_point.h>
46#include <pcl/common/io.h>
47
48namespace pcl
49{
50
51template <typename PointT> int
53 const std::string &field_name,
54 std::vector<pcl::PCLPointField> &fields)
55{
56 return getFieldIndex<PointT>(field_name, fields);
57}
58
59
60template <typename PointT> int
61getFieldIndex (const std::string &field_name,
62 std::vector<pcl::PCLPointField> &fields)
63{
64 fields = getFields<PointT> ();
65 const auto& ref = fields;
66 return pcl::getFieldIndex<PointT> (field_name, ref);
67}
68
69
70template <typename PointT> int
71getFieldIndex (const std::string &field_name,
72 const std::vector<pcl::PCLPointField> &fields)
73{
74 const auto result = std::find_if(fields.begin (), fields.end (),
75 [&field_name](const auto& field) { return field.name == field_name; });
76 if (result == fields.end ())
77 return -1;
78 return std::distance(fields.begin (), result);
79}
80
81
82template <typename PointT> void
83getFields (const pcl::PointCloud<PointT> &, std::vector<pcl::PCLPointField> &fields)
84{
85 fields = getFields<PointT> ();
86}
87
88
89template <typename PointT> void
90getFields (std::vector<pcl::PCLPointField> &fields)
91{
92 fields = getFields<PointT> ();
93}
94
95
96template <typename PointT> std::vector<pcl::PCLPointField>
98{
99 std::vector<pcl::PCLPointField> fields;
100 // Get the fields list
101 pcl::for_each_type<typename pcl::traits::fieldList<PointT>::type>(pcl::detail::FieldAdder<PointT>(fields));
102 return fields;
103}
104
105template <typename CloudT> inline std::vector<pcl::PCLPointField>
106getFields (const CloudT& /*cloud*/)
107{
108 return pcl::getFields<typename CloudT::PointType>();
109}
110
111// Template specialization for PCLPointCloud2
112template <> inline std::vector<pcl::PCLPointField>
114 return cloud.fields;
115}
116
117
118template <typename PointT> std::string
120{
121 // Get the fields list
122 const auto fields = getFields<PointT>();
123 std::string result;
124 for (std::size_t i = 0; i < fields.size () - 1; ++i)
125 result += fields[i].name + " ";
126 result += fields[fields.size () - 1].name;
127 return (result);
128}
129
130/**
131 * \brief reinterpret a pointer as a type, dereference it, and return result as target
132 * type
133 *
134 * \tparam DType Pointer type of the data
135 * \tparam RType Return type which the dereferenced result is cast to
136 *
137 * \return value
138 */
139template <typename DType, typename RType> RType reinterpret_and_cast (const std::uint8_t* p)
140{
141 return static_cast<RType>(*reinterpret_cast<const DType*>(p));
142}
143
144template <typename T> T point_field_as (const std::uint8_t* data, const std::uint8_t type)
145{
146 switch (type) {
148 return reinterpret_and_cast<float, T>(data);
149 break;
151 return reinterpret_and_cast<std::uint8_t, T>(data);
152 break;
154 return reinterpret_and_cast<std::uint16_t, T>(data);
155 break;
157 return reinterpret_and_cast<std::uint32_t, T>(data);
158 break;
160 return reinterpret_and_cast<std::uint64_t, T>(data);
161 break;
163 return reinterpret_and_cast<bool, T>(data);
164 break;
166 return reinterpret_and_cast<double, T>(data);
167 break;
169 return reinterpret_and_cast<std::int16_t, T>(data);
170 break;
172 return reinterpret_and_cast<std::int32_t, T>(data);
173 break;
175 return reinterpret_and_cast<std::int64_t, T>(data);
176 break;
177 default:
178 return 0;
179 break;
180 }
181}
182
183
184namespace detail
185{
186
187 template <typename PointInT, typename PointOutT> void
190 {
191 // Iterate over each point, if the point types of two clouds are different
192 for (std::size_t i = 0; i < cloud_in.size (); ++i)
193 copyPoint (cloud_in[i], cloud_out[i]);
194 }
195
196
197 template <typename PointT> void
199 pcl::PointCloud<PointT> &cloud_out)
200 {
201 // Use std::copy directly, if the point types of two clouds are same
202 std::copy (cloud_in.data(), cloud_in.data() + cloud_in.size (), cloud_out.data());
203 }
204
205} // namespace detail
206
207template <typename PointInT, typename PointOutT> void
210{
211 // Allocate enough space and copy the basics
212 cloud_out.header = cloud_in.header;
213 cloud_out.width = cloud_in.width;
214 cloud_out.height = cloud_in.height;
215 cloud_out.is_dense = cloud_in.is_dense;
216 cloud_out.sensor_orientation_ = cloud_in.sensor_orientation_;
217 cloud_out.sensor_origin_ = cloud_in.sensor_origin_;
218 cloud_out.resize (cloud_in.size ());
219
220 if (!cloud_in.empty ())
221 detail::copyPointCloudMemcpy (cloud_in, cloud_out);
222}
223
224
225template <typename PointT, typename IndicesVectorAllocator> void
228 pcl::PointCloud<PointT> &cloud_out)
229{
230 // Do we want to copy everything?
231 if (indices.size () == cloud_in.size ())
232 {
233 cloud_out = cloud_in;
234 return;
235 }
236
237 // Allocate enough space and copy the basics
238 cloud_out.clear ();
239 cloud_out.reserve (indices.size ());
240 cloud_out.header = cloud_in.header;
241 cloud_out.width = indices.size ();
242 cloud_out.height = 1;
243 cloud_out.is_dense = cloud_in.is_dense;
244 cloud_out.sensor_orientation_ = cloud_in.sensor_orientation_;
245 cloud_out.sensor_origin_ = cloud_in.sensor_origin_;
246
247 // Iterate over each point
248 for (const auto& index : indices)
249 cloud_out.transient_push_back (cloud_in[index]);
250}
251
252
253template <typename PointInT, typename PointOutT, typename IndicesVectorAllocator> void
257{
258 // Allocate enough space and copy the basics
259 cloud_out.resize (indices.size ());
260 cloud_out.header = cloud_in.header;
261 cloud_out.width = indices.size ();
262 cloud_out.height = 1;
263 cloud_out.is_dense = cloud_in.is_dense;
264 cloud_out.sensor_orientation_ = cloud_in.sensor_orientation_;
265 cloud_out.sensor_origin_ = cloud_in.sensor_origin_;
266
267 // Iterate over each point
268 for (std::size_t i = 0; i < indices.size (); ++i)
269 copyPoint (cloud_in[indices[i]], cloud_out[i]);
270}
271
272
273template <typename PointT> void
275 const pcl::PointIndices &indices,
276 pcl::PointCloud<PointT> &cloud_out)
277{
278 copyPointCloud (cloud_in, indices.indices, cloud_out);
279}
280
281
282template <typename PointInT, typename PointOutT> void
284 const pcl::PointIndices &indices,
286{
287 copyPointCloud (cloud_in, indices.indices, cloud_out);
288}
289
290
291template <typename PointT> void
293 const std::vector<pcl::PointIndices> &indices,
294 pcl::PointCloud<PointT> &cloud_out)
295{
296 std::size_t nr_p = 0;
297 for (const auto &index : indices)
298 nr_p += index.indices.size ();
299
300 // Do we want to copy everything? Remember we assume UNIQUE indices
301 if (nr_p == cloud_in.size ())
302 {
303 cloud_out = cloud_in;
304 return;
305 }
306
307 // Allocate enough space and copy the basics
308 cloud_out.clear ();
309 cloud_out.reserve (nr_p);
310 cloud_out.header = cloud_in.header;
311 cloud_out.width = nr_p;
312 cloud_out.height = 1;
313 cloud_out.is_dense = cloud_in.is_dense;
314 cloud_out.sensor_orientation_ = cloud_in.sensor_orientation_;
315 cloud_out.sensor_origin_ = cloud_in.sensor_origin_;
316
317 // Iterate over each cluster
318 for (const auto &cluster_index : indices)
319 {
320 // Iterate over each idx
321 for (const auto &index : cluster_index.indices)
322 {
323 // Iterate over each dimension
324 cloud_out.transient_push_back (cloud_in[index]);
325 }
326 }
327}
328
329
330template <typename PointInT, typename PointOutT> void
332 const std::vector<pcl::PointIndices> &indices,
334{
335 const auto nr_p = std::accumulate(indices.begin (), indices.end (), 0,
336 [](const auto& acc, const auto& index) { return index.indices.size() + acc; });
337
338 // Do we want to copy everything? Remember we assume UNIQUE indices
339 if (nr_p == cloud_in.size ())
340 {
341 copyPointCloud (cloud_in, cloud_out);
342 return;
343 }
344
345 // Allocate enough space and copy the basics
346 cloud_out.resize (nr_p);
347 cloud_out.header = cloud_in.header;
348 cloud_out.width = nr_p;
349 cloud_out.height = 1;
350 cloud_out.is_dense = cloud_in.is_dense;
351 cloud_out.sensor_orientation_ = cloud_in.sensor_orientation_;
352 cloud_out.sensor_origin_ = cloud_in.sensor_origin_;
353
354 // Iterate over each cluster
355 std::size_t cp = 0;
356 for (const auto &cluster_index : indices)
357 {
358 // Iterate over each idx
359 for (const auto &index : cluster_index.indices)
360 {
361 copyPoint (cloud_in[index], cloud_out[cp]);
362 ++cp;
363 }
364 }
365}
366
367
368template <typename PointIn1T, typename PointIn2T, typename PointOutT> void
370 const pcl::PointCloud<PointIn2T> &cloud2_in,
372{
373 using FieldList1 = typename pcl::traits::fieldList<PointIn1T>::type;
374 using FieldList2 = typename pcl::traits::fieldList<PointIn2T>::type;
375
376 if (cloud1_in.size () != cloud2_in.size ())
377 {
378 PCL_ERROR ("[pcl::concatenateFields] The number of points in the two input datasets differs!\n");
379 return;
380 }
381
382 // Resize the output dataset
383 cloud_out.resize (cloud1_in.size ());
384 cloud_out.header = cloud1_in.header;
385 cloud_out.width = cloud1_in.width;
386 cloud_out.height = cloud1_in.height;
387 if (!cloud1_in.is_dense || !cloud2_in.is_dense)
388 cloud_out.is_dense = false;
389 else
390 cloud_out.is_dense = true;
391
392 // Iterate over each point
393 for (std::size_t i = 0; i < cloud_out.size (); ++i)
394 {
395 // Iterate over each dimension
396 pcl::for_each_type <FieldList1> (pcl::NdConcatenateFunctor <PointIn1T, PointOutT> (cloud1_in[i], cloud_out[i]));
397 pcl::for_each_type <FieldList2> (pcl::NdConcatenateFunctor <PointIn2T, PointOutT> (cloud2_in[i], cloud_out[i]));
398 }
399}
400
401
402template <typename PointT> void
404 int top, int bottom, int left, int right, pcl::InterpolationType border_type, const PointT& value)
405{
406 if (top < 0 || left < 0 || bottom < 0 || right < 0)
407 {
408 std::string faulty = (top < 0) ? "top" : (left < 0) ? "left" : (bottom < 0) ? "bottom" : "right";
409 PCL_THROW_EXCEPTION (pcl::BadArgumentException, "[pcl::copyPointCloud] error: " << faulty << " must be positive!");
410 return;
411 }
412
413 if (top == 0 && left == 0 && bottom == 0 && right == 0)
414 cloud_out = cloud_in;
415 else
416 {
417 // Allocate enough space and copy the basics
418 cloud_out.header = cloud_in.header;
419 cloud_out.width = cloud_in.width + left + right;
420 cloud_out.height = cloud_in.height + top + bottom;
421 if (cloud_out.size () != cloud_out.width * cloud_out.height)
422 cloud_out.resize (cloud_out.width * cloud_out.height);
423 cloud_out.is_dense = cloud_in.is_dense;
424 cloud_out.sensor_orientation_ = cloud_in.sensor_orientation_;
425 cloud_out.sensor_origin_ = cloud_in.sensor_origin_;
426
427 if (border_type == pcl::BORDER_TRANSPARENT)
428 {
429 const PointT* in = cloud_in.data();
430 PointT* out = cloud_out.data();
431 PointT* out_inner = out + cloud_out.width*top + left;
432 for (std::uint32_t i = 0; i < cloud_in.height; i++, out_inner += cloud_out.width, in += cloud_in.width)
433 {
434 if (out_inner != in) {
435 std::copy(in, in + cloud_in.width, out_inner);
436 }
437 }
438 }
439 else
440 {
441 // Copy the data
442 if (border_type != pcl::BORDER_CONSTANT)
443 {
444 try
445 {
446 std::vector<int> padding (cloud_out.width - cloud_in.width);
447 int right = cloud_out.width - cloud_in.width - left;
448 int bottom = cloud_out.height - cloud_in.height - top;
449
450 for (int i = 0; i < left; i++)
451 padding[i] = pcl::interpolatePointIndex (i-left, cloud_in.width, border_type);
452
453 for (int i = 0; i < right; i++)
454 padding[i+left] = pcl::interpolatePointIndex (cloud_in.width+i, cloud_in.width, border_type);
455
456 const PointT* in = cloud_in.data();
457 PointT* out = cloud_out.data();
458 PointT* out_inner = out + cloud_out.width*top + left;
459
460 for (std::uint32_t i = 0; i < cloud_in.height; i++, out_inner += cloud_out.width, in += cloud_in.width)
461 {
462 if (out_inner != in) {
463 std::copy(in, in + cloud_in.width, out_inner);
464 }
465
466 for (int j = 0; j < left; j++)
467 out_inner[j - left] = in[padding[j]];
468
469 for (int j = 0; j < right; j++)
470 out_inner[j + cloud_in.width] = in[padding[j + left]];
471 }
472
473 for (int i = 0; i < top; i++)
474 {
475 int j = pcl::interpolatePointIndex (i - top, cloud_in.height, border_type);
476 std::copy(out + (j+top) * cloud_out.width, out + (j+top) * cloud_out.width + cloud_out.width,
477 out + i*cloud_out.width);
478 }
479
480 for (int i = 0; i < bottom; i++)
481 {
482 int j = pcl::interpolatePointIndex (i + cloud_in.height, cloud_in.height, border_type);
483 std::copy(out + (j+top)*cloud_out.width, out + (j+top)*cloud_out.width + cloud_out.width,
484 out + (i + cloud_in.height + top)*cloud_out.width);
485 }
486 }
488 {
489 PCL_ERROR ("[pcl::copyPointCloud] Unhandled interpolation type %d!\n", border_type);
490 }
491 }
492 else
493 {
494 int right = cloud_out.width - cloud_in.width - left;
495 int bottom = cloud_out.height - cloud_in.height - top;
496 std::vector<PointT> buff (cloud_out.width, value);
497 PointT* buff_ptr = buff.data();
498 const PointT* in = cloud_in.data();
499 PointT* out = cloud_out.data();
500 PointT* out_inner = out + cloud_out.width*top + left;
501
502 for (std::uint32_t i = 0; i < cloud_in.height; i++, out_inner += cloud_out.width, in += cloud_in.width)
503 {
504 if (out_inner != in) {
505 std::copy(in, in + cloud_in.width, out_inner);
506 }
507
508 std::copy(buff_ptr, buff_ptr + left, out_inner - left);
509 std::copy(buff_ptr, buff_ptr + right, out_inner + cloud_in.width);
510 }
511
512 for (int i = 0; i < top; i++)
513 {
514 std::copy(buff_ptr, buff_ptr + cloud_out.width, out + i*cloud_out.width);
515 }
516
517 for (int i = 0; i < bottom; i++)
518 {
519 std::copy(buff_ptr, buff_ptr + cloud_out.width,
520 out + (i + cloud_in.height + top)*cloud_out.width);
521 }
522 }
523 }
524 }
525}
526
527} // namespace pcl
An exception that is thrown when the arguments number or type is wrong/unhandled.
Definition exceptions.h:259
PointCloud represents the base class in PCL for storing collections of 3D points.
bool empty() const
bool is_dense
True if no points are invalid (e.g., have NaN or Inf values in any of their floating point fields).
void resize(std::size_t count)
Resizes the container to contain count elements.
PointT * data() noexcept
Eigen::Quaternionf sensor_orientation_
Sensor acquisition pose (rotation).
void transient_push_back(const PointT &pt)
Insert a new point in the cloud, at the end of the container.
std::uint32_t width
The point cloud width (if organized as an image-structure).
pcl::PCLHeader header
The point cloud header.
std::uint32_t height
The point cloud height (if organized as an image-structure).
void clear()
Removes all points in a cloud and sets the width and height to 0.
std::size_t size() const
Eigen::Vector4f sensor_origin_
Sensor acquisition pose (origin/translation).
void reserve(std::size_t n)
T point_field_as(const std::uint8_t *data, const std::uint8_t type)
Get the value of a point field from raw data pointer and field type.
Definition io.hpp:144
std::string getFieldsList(const pcl::PointCloud< PointT > &)
Get the list of all fields available in a given cloud.
Definition io.hpp:119
void copyPoint(const PointInT &point_in, PointOutT &point_out)
Copy the fields of a source point into a target point.
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:369
std::vector< pcl::PCLPointField > getFields()
Get the list of available fields (i.e., dimension/channel)
Definition io.hpp:97
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:208
void copyPointCloudMemcpy(const pcl::PointCloud< PointInT > &cloud_in, pcl::PointCloud< PointOutT > &cloud_out)
Definition io.hpp:188
int getFieldIndex(const pcl::PointCloud< PointT > &, const std::string &field_name, std::vector< pcl::PCLPointField > &fields)
Definition io.hpp:52
InterpolationType
Definition io.h:278
@ BORDER_TRANSPARENT
Definition io.h:281
@ BORDER_CONSTANT
Definition io.h:279
PCL_EXPORTS int interpolatePointIndex(int p, int length, InterpolationType type)
std::vector< index_t, Allocator > IndicesAllocator
Type used for indices in PCL.
Definition types.h:128
std::vector< pcl::PCLPointField > getFields< pcl::PCLPointCloud2 >(const pcl::PCLPointCloud2 &cloud)
Definition io.hpp:113
RType reinterpret_and_cast(const std::uint8_t *p)
reinterpret a pointer as a type, dereference it, and return result as target type
Definition io.hpp:139
std::vector<::pcl::PCLPointField > fields
A point structure representing Euclidean xyz coordinates, and the RGB color.