Point Cloud Library (PCL)  1.15.1-dev
point_representation.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  *
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * * Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  * * Redistributions in binary form must reproduce the above
16  * copyright notice, this list of conditions and the following
17  * disclaimer in the documentation and/or other materials provided
18  * with the distribution.
19  * * Neither the name of the copyright holder(s) nor the names of its
20  * contributors may be used to endorse or promote products derived
21  * from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  *
36  * $Id$
37  *
38  */
39 
40 #pragma once
41 
42 #include <algorithm>
43 #include <vector>
44 
45 #include <pcl/point_types.h>
46 #include <pcl/memory.h>
47 #include <pcl/pcl_macros.h>
48 #include <pcl/for_each_type.h>
49 
50 namespace pcl
51 {
52  /** \brief @b PointRepresentation provides a set of methods for converting a point structs/object into an
53  * n-dimensional vector.
54  * \note This is an abstract class. Subclasses must set nr_dimensions_ to the appropriate value in the constructor
55  * and provide an implementation of the pure virtual copyToFloatArray method.
56  * \author Michael Dixon
57  */
58  template <typename PointT>
60  {
61  protected:
62  /** \brief The number of dimensions in this point's vector (i.e. the "k" in "k-D") */
63  int nr_dimensions_ = 0;
64  /** \brief A vector containing the rescale factor to apply to each dimension. */
65  std::vector<float> alpha_;
66  /** \brief Indicates whether this point representation is trivial. It is trivial if and only if the following
67  * conditions hold:
68  * - the relevant data consists only of float values
69  * - the vectorize operation directly copies the first nr_dimensions_ elements of PointT to the out array
70  * - sizeof(PointT) is a multiple of sizeof(float)
71  * In short, a trivial point representation converts the input point to a float array that is the same as if
72  * the point was reinterpret_casted to a float array of length nr_dimensions_ . This value says that this
73  * representation can be trivial; it is only trivial if setRescaleValues() has not been set.
74  */
75  bool trivial_ = false;
76 
77  public:
78  using Ptr = shared_ptr<PointRepresentation<PointT> >;
79  using ConstPtr = shared_ptr<const PointRepresentation<PointT> >;
80 
81  /** \brief Empty destructor */
82  virtual ~PointRepresentation () = default;
83  //TODO: check if copy and move constructors / assignment operators are needed
84 
85  /** \brief Copy point data from input point to a float array. This method must be overridden in all subclasses.
86  * \param[in] p The input point
87  * \param[out] out A pointer to a float array.
88  */
89  virtual void copyToFloatArray (const PointT &p, float *out) const = 0;
90 
91  /** \brief Returns whether this point representation is trivial. It is trivial if and only if the following
92  * conditions hold:
93  * - the relevant data consists only of float values
94  * - the vectorize operation directly copies the first nr_dimensions_ elements of PointT to the out array
95  * - sizeof(PointT) is a multiple of sizeof(float)
96  * In short, a trivial point representation converts the input point to a float array that is the same as if
97  * the point was reinterpret_casted to a float array of length nr_dimensions_ . */
98  inline bool isTrivial() const { return trivial_ && alpha_.empty (); }
99 
100  /** \brief Verify that the input point is valid.
101  * \param p The point to validate
102  */
103  virtual bool
104  isValid (const PointT &p) const
105  {
106  bool is_valid = true;
107 
108  if (trivial_)
109  {
110  const float* temp = reinterpret_cast<const float*>(&p);
111 
112  for (int i = 0; i < nr_dimensions_; ++i)
113  {
114  if (!std::isfinite (temp[i]))
115  {
116  is_valid = false;
117  break;
118  }
119  }
120  }
121  else
122  {
123  float *temp = new float[nr_dimensions_];
124  copyToFloatArray (p, temp);
125 
126  for (int i = 0; i < nr_dimensions_; ++i)
127  {
128  if (!std::isfinite (temp[i]))
129  {
130  is_valid = false;
131  break;
132  }
133  }
134  delete [] temp;
135  }
136  return (is_valid);
137  }
138 
139  /** \brief Convert input point into a vector representation, rescaling by \a alpha.
140  * \param[in] p the input point
141  * \param[out] out The output vector. Can be of any type that implements the [] operator.
142  */
143  template <typename OutputType> void
144  vectorize (const PointT &p, OutputType &out) const
145  {
146  float *temp = new float[nr_dimensions_];
147  copyToFloatArray (p, temp);
148  if (alpha_.empty ())
149  {
150  for (int i = 0; i < nr_dimensions_; ++i)
151  out[i] = temp[i];
152  }
153  else
154  {
155  for (int i = 0; i < nr_dimensions_; ++i)
156  out[i] = temp[i] * alpha_[i];
157  }
158  delete [] temp;
159  }
160 
161  void
162  vectorize (const PointT &p, float* out) const
163  {
164  copyToFloatArray (p, out);
165  if (!alpha_.empty ())
166  for (int i = 0; i < nr_dimensions_; ++i)
167  out[i] *= alpha_[i];
168  }
169 
170  void
171  vectorize (const PointT &p, std::vector<float> &out) const
172  {
173  copyToFloatArray (p, out.data());
174  if (!alpha_.empty ())
175  for (int i = 0; i < nr_dimensions_; ++i)
176  out[i] *= alpha_[i];
177  }
178 
179  /** \brief Set the rescale values to use when vectorizing points
180  * \param[in] rescale_array The array/vector of rescale values. Can be of any type that implements the [] operator.
181  */
182  void
183  setRescaleValues (const float *rescale_array)
184  {
185  alpha_.resize (nr_dimensions_);
186  std::copy(rescale_array, rescale_array + nr_dimensions_, alpha_.begin());
187  }
188 
189  /** \brief Return the number of dimensions in the point's vector representation. */
190  inline int getNumberOfDimensions () const { return (nr_dimensions_); }
191  };
192 
193  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
194  /** \brief @b DefaultPointRepresentation extends PointRepresentation to define default behavior for common point types.
195  */
196  template <typename PointDefault>
197  class DefaultPointRepresentation : public PointRepresentation <PointDefault>
198  {
201 
202  public:
203  // Boost shared pointers
204  using Ptr = shared_ptr<DefaultPointRepresentation<PointDefault> >;
205  using ConstPtr = shared_ptr<const DefaultPointRepresentation<PointDefault> >;
206 
207  static constexpr const std::int32_t NR_DIMS = std::min<std::int32_t>(sizeof (PointDefault) / sizeof (float), 3);
208 
210  {
211  // If point type is unknown, assume it's a struct/array of floats, and compute the number of dimensions
212  nr_dimensions_ = sizeof (PointDefault) / sizeof (float);
213  // Limit the default representation to the first 3 elements
214  if (nr_dimensions_ > 3) nr_dimensions_ = 3;
215 
216  trivial_ = true;
217  }
218 
219  ~DefaultPointRepresentation () override = default;
220 
221  inline Ptr
222  makeShared () const
223  {
224  return (Ptr (new DefaultPointRepresentation<PointDefault> (*this)));
225  }
226 
227  void
228  copyToFloatArray (const PointDefault &p, float * out) const override
229  {
230  // If point type is unknown, treat it as a struct/array of floats
231  const float* ptr = reinterpret_cast<const float*> (&p);
232  std::copy(ptr, ptr + nr_dimensions_, out);
233  }
234  };
235 
236  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
237  /** \brief @b DefaulFeatureRepresentation extends PointRepresentation and is intended to be used when defining the
238  * default behavior for feature descriptor types (i.e., copy each element of each field into a float array).
239  */
240  template <typename PointDefault>
241  class DefaultFeatureRepresentation : public PointRepresentation <PointDefault>
242  {
243  protected:
245 
246  private:
247  struct IncrementFunctor
248  {
249  IncrementFunctor (int &n) : n_ (n)
250  {
251  n_ = 0;
252  }
253 
254  template<typename Key> inline void operator () ()
255  {
256  n_ += pcl::traits::datatype<PointDefault, Key>::size;
257  }
258 
259  private:
260  int &n_;
261  };
262 
263  struct NdCopyPointFunctor
264  {
265  using Pod = typename traits::POD<PointDefault>::type;
266 
267  NdCopyPointFunctor (const PointDefault &p1, float * p2)
268  : p1_ (reinterpret_cast<const Pod&>(p1)), p2_ (p2) {}
269 
270  template<typename Key> inline void operator() ()
271  {
272  using FieldT = typename pcl::traits::datatype<PointDefault, Key>::type;
273  constexpr int NrDims = pcl::traits::datatype<PointDefault, Key>::size;
274  Helper<Key, FieldT, NrDims>::copyPoint (p1_, p2_, f_idx_);
275  }
276 
277  // Copy helper for scalar fields
278  template <typename Key, typename FieldT, int NrDims>
279  struct Helper
280  {
281  static void copyPoint (const Pod &p1, float * p2, int &f_idx)
282  {
283  const std::uint8_t * data_ptr = reinterpret_cast<const std::uint8_t *> (&p1) +
284  pcl::traits::offset<PointDefault, Key>::value;
285  p2[f_idx++] = *reinterpret_cast<const FieldT*> (data_ptr);
286  }
287  };
288  // Copy helper for array fields
289  template <typename Key, typename FieldT, int NrDims>
290  struct Helper<Key, FieldT[NrDims], NrDims>
291  {
292  static void copyPoint (const Pod &p1, float * p2, int &f_idx)
293  {
294  const std::uint8_t * data_ptr = reinterpret_cast<const std::uint8_t *> (&p1) +
295  pcl::traits::offset<PointDefault, Key>::value;
296  int nr_dims = NrDims;
297  const FieldT * array = reinterpret_cast<const FieldT *> (data_ptr);
298  for (int i = 0; i < nr_dims; ++i)
299  {
300  p2[f_idx++] = array[i];
301  }
302  }
303  };
304 
305  private:
306  const Pod &p1_;
307  float * p2_;
308  int f_idx_{0};
309  };
310 
311  public:
312  // Boost shared pointers
313  using Ptr = shared_ptr<DefaultFeatureRepresentation<PointDefault>>;
314  using ConstPtr = shared_ptr<const DefaultFeatureRepresentation<PointDefault>>;
315  using FieldList = typename pcl::traits::fieldList<PointDefault>::type;
316 
317  static constexpr const std::int32_t NR_DIMS = pcl::detail::traits::descriptorSize_v<PointDefault>;
318 
320  {
321  nr_dimensions_ = 0; // zero-out the nr_dimensions_ before it gets incremented
322  pcl::for_each_type <FieldList> (IncrementFunctor (nr_dimensions_));
323  }
324 
325  inline Ptr
326  makeShared () const
327  {
328  return (Ptr (new DefaultFeatureRepresentation<PointDefault> (*this)));
329  }
330 
331  void
332  copyToFloatArray (const PointDefault &p, float * out) const override
333  {
334  pcl::for_each_type <FieldList> (NdCopyPointFunctor (p, out));
335  }
336  };
337 
338  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
339  template <>
341  {
342  public:
343  static constexpr const std::int32_t NR_DIMS = 3;
344 
346  {
348  trivial_ = true;
349  }
350 
351  void
352  copyToFloatArray (const PointXYZ &p, float * out) const override
353  {
354  out[0] = p.x;
355  out[1] = p.y;
356  out[2] = p.z;
357  }
358  };
359 
360  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
361  template <>
363  {
364  public:
365  static constexpr const std::int32_t NR_DIMS = 3;
366 
368  {
370  trivial_ = true;
371  }
372 
373  void
374  copyToFloatArray (const PointXYZI &p, float * out) const override
375  {
376  out[0] = p.x;
377  out[1] = p.y;
378  out[2] = p.z;
379  // By default, p.intensity is not part of the PointXYZI vectorization
380  }
381  };
382 
383  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
384  template <>
386  {
387  public:
388  static constexpr const std::int32_t NR_DIMS = 3;
389 
391  {
393  trivial_ = true;
394  }
395 
396  void
397  copyToFloatArray (const PointNormal &p, float * out) const override
398  {
399  out[0] = p.x;
400  out[1] = p.y;
401  out[2] = p.z;
402  }
403  };
404 
405  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
406  template <>
408  {};
409 
410  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
411  template <>
413  {};
414 
415  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
416  template <>
418  {
419  public:
420  static constexpr const std::int32_t NR_DIMS = 4;
421 
423  {
425  trivial_ = true;
426  }
427 
428  void
429  copyToFloatArray (const PPFSignature &p, float * out) const override
430  {
431  out[0] = p.f1;
432  out[1] = p.f2;
433  out[2] = p.f3;
434  out[3] = p.f4;
435  }
436  };
437 
438  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
439  template <>
441  {};
442 
443  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
444  template <>
446  {};
447 
448  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
449  template <>
451  {};
452 
453  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
454  template <>
456  {};
457 
458  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
459  template <>
461  {};
462 
463  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
464  template <>
466  {
467  public:
468  static constexpr const std::int32_t NR_DIMS = 36;
469 
471  {
473  trivial_=false;
474  }
475 
476  void
477  copyToFloatArray (const Narf36 &p, float * out) const override
478  {
479  for (int i = 0; i < nr_dimensions_; ++i)
480  out[i] = p.descriptor[i];
481  }
482  };
483  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
484  template <>
486  {};
487 
488  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
489  template <>
491  {
492  public:
493  static constexpr const std::int32_t NR_DIMS = 1980;
494 
496  {
498  }
499 
500  void
501  copyToFloatArray (const ShapeContext1980 &p, float * out) const override
502  {
503  for (int i = 0; i < nr_dimensions_; ++i)
504  out[i] = p.descriptor[i];
505  }
506  };
507 
508  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
509  template <>
511  {
512  public:
513  static constexpr const std::int32_t NR_DIMS = 1960;
514 
516  {
518  }
519 
520  void
521  copyToFloatArray (const UniqueShapeContext1960 &p, float * out) const override
522  {
523  for (int i = 0; i < nr_dimensions_; ++i)
524  out[i] = p.descriptor[i];
525  }
526  };
527 
528  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
529  template <>
531  {
532  public:
533  static constexpr const std::int32_t NR_DIMS = 352;
534 
536  {
538  }
539 
540  void
541  copyToFloatArray (const SHOT352 &p, float * out) const override
542  {
543  for (int i = 0; i < nr_dimensions_; ++i)
544  out[i] = p.descriptor[i];
545  }
546  };
547 
548  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
549  template <>
551  {
552  public:
553  static constexpr const std::int32_t NR_DIMS = 1344;
554 
556  {
558  }
559 
560  void
561  copyToFloatArray (const SHOT1344 &p, float * out) const override
562  {
563  for (int i = 0; i < nr_dimensions_; ++i)
564  out[i] = p.descriptor[i];
565  }
566  };
567 
568 
569  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
570  /** \brief @b CustomPointRepresentation extends PointRepresentation to allow for sub-part selection on the point.
571  */
572  template <typename PointDefault>
573  class CustomPointRepresentation : public PointRepresentation <PointDefault>
574  {
576 
577  public:
578  // Boost shared pointers
579  using Ptr = shared_ptr<CustomPointRepresentation<PointDefault> >;
580  using ConstPtr = shared_ptr<const CustomPointRepresentation<PointDefault> >;
581 
582  /** \brief Constructor
583  * \param[in] max_dim the maximum number of dimensions to use
584  * \param[in] start_dim the starting dimension
585  */
586  CustomPointRepresentation (const int max_dim = 3, const int start_dim = 0)
587  : max_dim_(max_dim), start_dim_(start_dim)
588  {
589  // If point type is unknown, assume it's a struct/array of floats, and compute the number of dimensions
590  nr_dimensions_ = static_cast<int> (sizeof (PointDefault) / sizeof (float)) - start_dim_;
591  // Limit the default representation to the first 3 elements
592  if (nr_dimensions_ > max_dim_)
594  }
595 
596  inline Ptr
597  makeShared () const
598  {
599  return Ptr (new CustomPointRepresentation<PointDefault> (*this));
600  }
601 
602  /** \brief Copy the point data into a float array
603  * \param[in] p the input point
604  * \param[out] out the resultant output array
605  */
606  void
607  copyToFloatArray (const PointDefault &p, float *out) const override
608  {
609  // If point type is unknown, treat it as a struct/array of floats
610  const float *ptr = (reinterpret_cast<const float*> (&p)) + start_dim_;
611  std::copy(ptr, ptr + nr_dimensions_, out);
612  }
613 
614  protected:
615  /** \brief Use at most this many dimensions (i.e. the "k" in "k-D" is at most max_dim_) -- \note float fields are assumed */
616  int max_dim_;
617  /** \brief Use dimensions only starting with this one (i.e. the "k" in "k-D" is = dim - start_dim_) -- \note float fields are assumed */
619  };
620 }
CustomPointRepresentation extends PointRepresentation to allow for sub-part selection on the point.
void copyToFloatArray(const PointDefault &p, float *out) const override
Copy the point data into a float array.
CustomPointRepresentation(const int max_dim=3, const int start_dim=0)
Constructor.
int max_dim_
Use at most this many dimensions (i.e.
shared_ptr< CustomPointRepresentation< PointDefault > > Ptr
shared_ptr< const CustomPointRepresentation< PointDefault > > ConstPtr
int start_dim_
Use dimensions only starting with this one (i.e.
DefaulFeatureRepresentation extends PointRepresentation and is intended to be used when defining the ...
shared_ptr< DefaultFeatureRepresentation< PointDefault > > Ptr
typename pcl::traits::fieldList< PointDefault >::type FieldList
static constexpr const std::int32_t NR_DIMS
void copyToFloatArray(const PointDefault &p, float *out) const override
Copy point data from input point to a float array.
shared_ptr< const DefaultFeatureRepresentation< PointDefault > > ConstPtr
void copyToFloatArray(const Narf36 &p, float *out) const override
Copy point data from input point to a float array.
void copyToFloatArray(const PPFSignature &p, float *out) const override
Copy point data from input point to a float array.
void copyToFloatArray(const PointNormal &p, float *out) const override
Copy point data from input point to a float array.
void copyToFloatArray(const PointXYZ &p, float *out) const override
Copy point data from input point to a float array.
void copyToFloatArray(const PointXYZI &p, float *out) const override
Copy point data from input point to a float array.
void copyToFloatArray(const SHOT1344 &p, float *out) const override
Copy point data from input point to a float array.
void copyToFloatArray(const SHOT352 &p, float *out) const override
Copy point data from input point to a float array.
void copyToFloatArray(const ShapeContext1980 &p, float *out) const override
Copy point data from input point to a float array.
void copyToFloatArray(const UniqueShapeContext1960 &p, float *out) const override
Copy point data from input point to a float array.
DefaultPointRepresentation extends PointRepresentation to define default behavior for common point ty...
shared_ptr< DefaultPointRepresentation< PointDefault > > Ptr
shared_ptr< const DefaultPointRepresentation< PointDefault > > ConstPtr
~DefaultPointRepresentation() override=default
void copyToFloatArray(const PointDefault &p, float *out) const override
Copy point data from input point to a float array.
static constexpr const std::int32_t NR_DIMS
PointRepresentation provides a set of methods for converting a point structs/object into an n-dimensi...
void vectorize(const PointT &p, float *out) const
shared_ptr< const PointRepresentation< PointT > > ConstPtr
virtual void copyToFloatArray(const PointT &p, float *out) const =0
Copy point data from input point to a float array.
void vectorize(const PointT &p, std::vector< float > &out) const
int nr_dimensions_
The number of dimensions in this point's vector (i.e.
bool trivial_
Indicates whether this point representation is trivial.
int getNumberOfDimensions() const
Return the number of dimensions in the point's vector representation.
bool isTrivial() const
Returns whether this point representation is trivial.
void setRescaleValues(const float *rescale_array)
Set the rescale values to use when vectorizing points.
shared_ptr< PointRepresentation< PointT > > Ptr
std::vector< float > alpha_
A vector containing the rescale factor to apply to each dimension.
virtual bool isValid(const PointT &p) const
Verify that the input point is valid.
void vectorize(const PointT &p, OutputType &out) const
Convert input point into a vector representation, rescaling by alpha.
virtual ~PointRepresentation()=default
Empty destructor.
Defines all the PCL implemented PointT point type structures.
Defines functions, macros and traits for allocating and using memory.
Defines all the PCL and non-PCL macros used.
static void copyPoint(const Pod &p1, float *p2, int &f_idx)
A point structure representing the Fast Point Feature Histogram (FPFH).
A point structure representing the Globally Aligned Spatial Distribution (GASD) shape descriptor.
A point structure representing the Globally Aligned Spatial Distribution (GASD) shape and color descr...
A point structure representing the Globally Aligned Spatial Distribution (GASD) shape and color descr...
A point structure representing the Narf descriptor.
float descriptor[36]
A point structure representing the Normal Based Signature for a feature matrix of 4-by-3.
A point structure representing the Point Feature Histogram with colors (PFHRGB).
A point structure representing the Point Feature Histogram (PFH).
A point structure for storing the Point Pair Feature (PPF) values.
A point structure representing Euclidean xyz coordinates, together with normal coordinates and the su...
A point structure representing Euclidean xyz coordinates.
A point structure representing Euclidean xyz coordinates, and the RGB color.
A point structure representing the generic Signature of Histograms of OrienTations (SHOT) - shape+col...
float descriptor[1344]
A point structure representing the generic Signature of Histograms of OrienTations (SHOT) - shape onl...
float descriptor[352]
A point structure representing a Shape Context.
A point structure representing a Unique Shape Context.
A point structure representing the Viewpoint Feature Histogram (VFH).