Point Cloud Library (PCL)  1.11.1-dev
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 #include <pcl/point_types.h>
48 
49 
50 namespace pcl
51 {
52 
53 template <typename PointT> int
55  const std::string &field_name,
56  std::vector<pcl::PCLPointField> &fields)
57 {
58  return getFieldIndex<PointT>(field_name, fields);
59 }
60 
61 
62 template <typename PointT> int
63 getFieldIndex (const std::string &field_name,
64  std::vector<pcl::PCLPointField> &fields)
65 {
66  fields = getFields<PointT> ();
67  const auto& ref = fields;
68  return pcl::getFieldIndex<PointT> (field_name, ref);
69 }
70 
71 
72 template <typename PointT> int
73 getFieldIndex (const std::string &field_name,
74  const std::vector<pcl::PCLPointField> &fields)
75 {
76  const auto result = std::find_if(fields.begin (), fields.end (),
77  [&field_name](const auto& field) { return field.name == field_name; });
78  if (result == fields.end ())
79  return -1;
80  return std::distance(fields.begin (), result);
81 }
82 
83 
84 template <typename PointT> void
85 getFields (const pcl::PointCloud<PointT> &, std::vector<pcl::PCLPointField> &fields)
86 {
87  fields = getFields<PointT> ();
88 }
89 
90 
91 template <typename PointT> void
92 getFields (std::vector<pcl::PCLPointField> &fields)
93 {
94  fields = getFields<PointT> ();
95 }
96 
97 
98 template <typename PointT> std::vector<pcl::PCLPointField>
100 {
101  std::vector<pcl::PCLPointField> fields;
102  // Get the fields list
103  pcl::for_each_type<typename pcl::traits::fieldList<PointT>::type>(pcl::detail::FieldAdder<PointT>(fields));
104  return fields;
105 }
106 
107 
108 template <typename PointT> std::string
110 {
111  // Get the fields list
112  const auto fields = getFields<PointT>();
113  std::string result;
114  for (std::size_t i = 0; i < fields.size () - 1; ++i)
115  result += fields[i].name + " ";
116  result += fields[fields.size () - 1].name;
117  return (result);
118 }
119 
120 
121 template <typename PointInT, typename PointOutT> void
123  pcl::PointCloud<PointOutT> &cloud_out)
124 {
125  // Allocate enough space and copy the basics
126  cloud_out.header = cloud_in.header;
127  cloud_out.width = cloud_in.width;
128  cloud_out.height = cloud_in.height;
129  cloud_out.is_dense = cloud_in.is_dense;
130  cloud_out.sensor_orientation_ = cloud_in.sensor_orientation_;
131  cloud_out.sensor_origin_ = cloud_in.sensor_origin_;
132  cloud_out.resize (cloud_in.size ());
133 
134  if (cloud_in.empty ())
135  return;
136 
137  if (isSamePointType<PointInT, PointOutT> ())
138  // Copy the whole memory block
139  memcpy (&cloud_out[0], &cloud_in[0], cloud_in.size () * sizeof (PointInT));
140  else
141  // Iterate over each point
142  for (std::size_t i = 0; i < cloud_in.size (); ++i)
143  copyPoint (cloud_in[i], cloud_out[i]);
144 }
145 
146 
147 template <typename PointT, typename IndicesVectorAllocator> void
150  pcl::PointCloud<PointT> &cloud_out)
151 {
152  // Do we want to copy everything?
153  if (indices.size () == cloud_in.size ())
154  {
155  cloud_out = cloud_in;
156  return;
157  }
158 
159  // Allocate enough space and copy the basics
160  cloud_out.resize (indices.size ());
161  cloud_out.header = cloud_in.header;
162  cloud_out.width = indices.size ();
163  cloud_out.height = 1;
164  cloud_out.is_dense = cloud_in.is_dense;
165  cloud_out.sensor_orientation_ = cloud_in.sensor_orientation_;
166  cloud_out.sensor_origin_ = cloud_in.sensor_origin_;
167 
168  // Iterate over each point
169  for (std::size_t i = 0; i < indices.size (); ++i)
170  cloud_out[i] = cloud_in[indices[i]];
171 }
172 
173 
174 template <typename PointInT, typename PointOutT, typename IndicesVectorAllocator> void
177  pcl::PointCloud<PointOutT> &cloud_out)
178 {
179  // Allocate enough space and copy the basics
180  cloud_out.resize (indices.size ());
181  cloud_out.header = cloud_in.header;
182  cloud_out.width = indices.size ();
183  cloud_out.height = 1;
184  cloud_out.is_dense = cloud_in.is_dense;
185  cloud_out.sensor_orientation_ = cloud_in.sensor_orientation_;
186  cloud_out.sensor_origin_ = cloud_in.sensor_origin_;
187 
188  // Iterate over each point
189  for (std::size_t i = 0; i < indices.size (); ++i)
190  copyPoint (cloud_in[indices[i]], cloud_out[i]);
191 }
192 
193 
194 template <typename PointT> void
196  const pcl::PointIndices &indices,
197  pcl::PointCloud<PointT> &cloud_out)
198 {
199  // Do we want to copy everything?
200  if (indices.indices.size () == cloud_in.size ())
201  {
202  cloud_out = cloud_in;
203  return;
204  }
205 
206  // Allocate enough space and copy the basics
207  cloud_out.resize (indices.indices.size ());
208  cloud_out.header = cloud_in.header;
209  cloud_out.width = indices.indices.size ();
210  cloud_out.height = 1;
211  cloud_out.is_dense = cloud_in.is_dense;
212  cloud_out.sensor_orientation_ = cloud_in.sensor_orientation_;
213  cloud_out.sensor_origin_ = cloud_in.sensor_origin_;
214 
215  // Iterate over each point
216  for (std::size_t i = 0; i < indices.indices.size (); ++i)
217  cloud_out[i] = cloud_in[indices.indices[i]];
218 }
219 
220 
221 template <typename PointInT, typename PointOutT> void
223  const pcl::PointIndices &indices,
224  pcl::PointCloud<PointOutT> &cloud_out)
225 {
226  copyPointCloud (cloud_in, indices.indices, cloud_out);
227 }
228 
229 
230 template <typename PointT> void
232  const std::vector<pcl::PointIndices> &indices,
233  pcl::PointCloud<PointT> &cloud_out)
234 {
235  int nr_p = 0;
236  for (const auto &index : indices)
237  nr_p += index.indices.size ();
238 
239  // Do we want to copy everything? Remember we assume UNIQUE indices
240  if (nr_p == cloud_in.size ())
241  {
242  cloud_out = cloud_in;
243  return;
244  }
245 
246  // Allocate enough space and copy the basics
247  cloud_out.resize (nr_p);
248  cloud_out.header = cloud_in.header;
249  cloud_out.width = nr_p;
250  cloud_out.height = 1;
251  cloud_out.is_dense = cloud_in.is_dense;
252  cloud_out.sensor_orientation_ = cloud_in.sensor_orientation_;
253  cloud_out.sensor_origin_ = cloud_in.sensor_origin_;
254 
255  // Iterate over each cluster
256  int cp = 0;
257  for (const auto &cluster_index : indices)
258  {
259  // Iterate over each idx
260  for (const auto &index : cluster_index.indices)
261  {
262  // Iterate over each dimension
263  cloud_out[cp] = cloud_in[index];
264  cp++;
265  }
266  }
267 }
268 
269 
270 template <typename PointInT, typename PointOutT> void
272  const std::vector<pcl::PointIndices> &indices,
273  pcl::PointCloud<PointOutT> &cloud_out)
274 {
275  const auto nr_p = std::accumulate(indices.begin (), indices.end (), 0,
276  [](const auto& acc, const auto& index) { return index.indices.size() + acc; });
277 
278  // Do we want to copy everything? Remember we assume UNIQUE indices
279  if (nr_p == cloud_in.size ())
280  {
281  copyPointCloud (cloud_in, cloud_out);
282  return;
283  }
284 
285  // Allocate enough space and copy the basics
286  cloud_out.resize (nr_p);
287  cloud_out.header = cloud_in.header;
288  cloud_out.width = nr_p;
289  cloud_out.height = 1;
290  cloud_out.is_dense = cloud_in.is_dense;
291  cloud_out.sensor_orientation_ = cloud_in.sensor_orientation_;
292  cloud_out.sensor_origin_ = cloud_in.sensor_origin_;
293 
294  // Iterate over each cluster
295  std::size_t cp = 0;
296  for (const auto &cluster_index : indices)
297  {
298  // Iterate over each idx
299  for (const auto &index : cluster_index.indices)
300  {
301  copyPoint (cloud_in[index], cloud_out[cp]);
302  ++cp;
303  }
304  }
305 }
306 
307 
308 template <typename PointIn1T, typename PointIn2T, typename PointOutT> void
310  const pcl::PointCloud<PointIn2T> &cloud2_in,
311  pcl::PointCloud<PointOutT> &cloud_out)
312 {
313  using FieldList1 = typename pcl::traits::fieldList<PointIn1T>::type;
314  using FieldList2 = typename pcl::traits::fieldList<PointIn2T>::type;
315 
316  if (cloud1_in.size () != cloud2_in.size ())
317  {
318  PCL_ERROR ("[pcl::concatenateFields] The number of points in the two input datasets differs!\n");
319  return;
320  }
321 
322  // Resize the output dataset
323  cloud_out.resize (cloud1_in.size ());
324  cloud_out.header = cloud1_in.header;
325  cloud_out.width = cloud1_in.width;
326  cloud_out.height = cloud1_in.height;
327  if (!cloud1_in.is_dense || !cloud2_in.is_dense)
328  cloud_out.is_dense = false;
329  else
330  cloud_out.is_dense = true;
331 
332  // Iterate over each point
333  for (std::size_t i = 0; i < cloud_out.size (); ++i)
334  {
335  // Iterate over each dimension
336  pcl::for_each_type <FieldList1> (pcl::NdConcatenateFunctor <PointIn1T, PointOutT> (cloud1_in[i], cloud_out[i]));
337  pcl::for_each_type <FieldList2> (pcl::NdConcatenateFunctor <PointIn2T, PointOutT> (cloud2_in[i], cloud_out[i]));
338  }
339 }
340 
341 
342 template <typename PointT> void
344  int top, int bottom, int left, int right, pcl::InterpolationType border_type, const PointT& value)
345 {
346  if (top < 0 || left < 0 || bottom < 0 || right < 0)
347  {
348  std::string faulty = (top < 0) ? "top" : (left < 0) ? "left" : (bottom < 0) ? "bottom" : "right";
349  PCL_THROW_EXCEPTION (pcl::BadArgumentException, "[pcl::copyPointCloud] error: " << faulty << " must be positive!");
350  return;
351  }
352 
353  if (top == 0 && left == 0 && bottom == 0 && right == 0)
354  cloud_out = cloud_in;
355  else
356  {
357  // Allocate enough space and copy the basics
358  cloud_out.header = cloud_in.header;
359  cloud_out.width = cloud_in.width + left + right;
360  cloud_out.height = cloud_in.height + top + bottom;
361  if (cloud_out.size () != cloud_out.width * cloud_out.height)
362  cloud_out.resize (cloud_out.width * cloud_out.height);
363  cloud_out.is_dense = cloud_in.is_dense;
364  cloud_out.sensor_orientation_ = cloud_in.sensor_orientation_;
365  cloud_out.sensor_origin_ = cloud_in.sensor_origin_;
366 
367  if (border_type == pcl::BORDER_TRANSPARENT)
368  {
369  const PointT* in = &(cloud_in[0]);
370  PointT* out = &(cloud_out[0]);
371  PointT* out_inner = out + cloud_out.width*top + left;
372  for (std::uint32_t i = 0; i < cloud_in.height; i++, out_inner += cloud_out.width, in += cloud_in.width)
373  {
374  if (out_inner != in)
375  memcpy (out_inner, in, cloud_in.width * sizeof (PointT));
376  }
377  }
378  else
379  {
380  // Copy the data
381  if (border_type != pcl::BORDER_CONSTANT)
382  {
383  try
384  {
385  std::vector<int> padding (cloud_out.width - cloud_in.width);
386  int right = cloud_out.width - cloud_in.width - left;
387  int bottom = cloud_out.height - cloud_in.height - top;
388 
389  for (int i = 0; i < left; i++)
390  padding[i] = pcl::interpolatePointIndex (i-left, cloud_in.width, border_type);
391 
392  for (int i = 0; i < right; i++)
393  padding[i+left] = pcl::interpolatePointIndex (cloud_in.width+i, cloud_in.width, border_type);
394 
395  const PointT* in = &(cloud_in[0]);
396  PointT* out = &(cloud_out[0]);
397  PointT* out_inner = out + cloud_out.width*top + left;
398 
399  for (std::uint32_t i = 0; i < cloud_in.height; i++, out_inner += cloud_out.width, in += cloud_in.width)
400  {
401  if (out_inner != in)
402  memcpy (out_inner, in, cloud_in.width * sizeof (PointT));
403 
404  for (int j = 0; j < left; j++)
405  out_inner[j - left] = in[padding[j]];
406 
407  for (int j = 0; j < right; j++)
408  out_inner[j + cloud_in.width] = in[padding[j + left]];
409  }
410 
411  for (int i = 0; i < top; i++)
412  {
413  int j = pcl::interpolatePointIndex (i - top, cloud_in.height, border_type);
414  memcpy (out + i*cloud_out.width,
415  out + (j+top) * cloud_out.width,
416  sizeof (PointT) * cloud_out.width);
417  }
418 
419  for (int i = 0; i < bottom; i++)
420  {
421  int j = pcl::interpolatePointIndex (i + cloud_in.height, cloud_in.height, border_type);
422  memcpy (out + (i + cloud_in.height + top)*cloud_out.width,
423  out + (j+top)*cloud_out.width,
424  cloud_out.width * sizeof (PointT));
425  }
426  }
428  {
429  PCL_ERROR ("[pcl::copyPointCloud] Unhandled interpolation type %d!\n", border_type);
430  }
431  }
432  else
433  {
434  int right = cloud_out.width - cloud_in.width - left;
435  int bottom = cloud_out.height - cloud_in.height - top;
436  std::vector<PointT> buff (cloud_out.width, value);
437  PointT* buff_ptr = &(buff[0]);
438  const PointT* in = &(cloud_in[0]);
439  PointT* out = &(cloud_out[0]);
440  PointT* out_inner = out + cloud_out.width*top + left;
441 
442  for (std::uint32_t i = 0; i < cloud_in.height; i++, out_inner += cloud_out.width, in += cloud_in.width)
443  {
444  if (out_inner != in)
445  memcpy (out_inner, in, cloud_in.width * sizeof (PointT));
446 
447  memcpy (out_inner - left, buff_ptr, left * sizeof (PointT));
448  memcpy (out_inner + cloud_in.width, buff_ptr, right * sizeof (PointT));
449  }
450 
451  for (int i = 0; i < top; i++)
452  {
453  memcpy (out + i*cloud_out.width, buff_ptr, cloud_out.width * sizeof (PointT));
454  }
455 
456  for (int i = 0; i < bottom; i++)
457  {
458  memcpy (out + (i + cloud_in.height + top)*cloud_out.width,
459  buff_ptr,
460  cloud_out.width * sizeof (PointT));
461  }
462  }
463  }
464  }
465 }
466 
467 } // namespace pcl
468 
pcl::concatenateFields
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:309
pcl
Definition: convolution.h:46
point_types.h
pcl::PointCloud::height
std::uint32_t height
The point cloud height (if organized as an image-structure).
Definition: point_cloud.h:393
pcl::geometry::distance
float distance(const PointT &p1, const PointT &p2)
Definition: geometry.h:60
pcl::PointCloud::empty
bool empty() const
Definition: point_cloud.h:439
pcl::PointIndices::indices
Indices indices
Definition: PointIndices.h:21
pcl::BORDER_CONSTANT
@ BORDER_CONSTANT
Definition: io.h:223
pcl::getFields
void getFields(const pcl::PointCloud< PointT > &, std::vector< pcl::PCLPointField > &fields)
Definition: io.hpp:85
pcl::NdConcatenateFunctor
Helper functor structure for concatenate.
Definition: concatenate.h:49
pcl::PointCloud
PointCloud represents the base class in PCL for storing collections of 3D points.
Definition: distances.h:55
pcl::BORDER_TRANSPARENT
@ BORDER_TRANSPARENT
Definition: io.h:225
pcl::PointXYZRGB
A point structure representing Euclidean xyz coordinates, and the RGB color.
Definition: point_types.hpp:628
pcl::copyPointCloud
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:122
pcl::PointCloud::width
std::uint32_t width
The point cloud width (if organized as an image-structure).
Definition: point_cloud.h:391
pcl::copyPoint
void copyPoint(const PointInT &point_in, PointOutT &point_out)
Copy the fields of a source point into a target point.
Definition: copy_point.hpp:137
pcl::BadArgumentException
An exception that is thrown when the arguments number or type is wrong/unhandled.
Definition: exceptions.h:255
pcl::PointCloud::sensor_origin_
Eigen::Vector4f sensor_origin_
Sensor acquisition pose (origin/translation).
Definition: point_cloud.h:399
pcl::PointCloud::sensor_orientation_
Eigen::Quaternionf sensor_orientation_
Sensor acquisition pose (rotation).
Definition: point_cloud.h:401
pcl::InterpolationType
InterpolationType
Definition: io.h:221
pcl::PointCloud::is_dense
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:396
pcl::PointCloud::resize
void resize(std::size_t count)
Resizes the container to contain count elements.
Definition: point_cloud.h:455
pcl::PointIndices
Definition: PointIndices.h:11
pcl::PointCloud::header
pcl::PCLHeader header
The point cloud header.
Definition: point_cloud.h:385
pcl::PointCloud::size
std::size_t size() const
Definition: point_cloud.h:436
pcl::IndicesAllocator
std::vector< index_t, Allocator > IndicesAllocator
Type used for indices in PCL.
Definition: types.h:126
pcl::interpolatePointIndex
PCL_EXPORTS int interpolatePointIndex(int p, int length, InterpolationType type)
pcl::getFieldIndex
int getFieldIndex(const pcl::PointCloud< PointT > &, const std::string &field_name, std::vector< pcl::PCLPointField > &fields)
Definition: io.hpp:54
pcl::getFieldsList
std::string getFieldsList(const pcl::PointCloud< PointT > &)
Get the list of all fields available in a given cloud.
Definition: io.hpp:109
pcl::detail::FieldAdder
Definition: conversions.h:63