Point Cloud Library (PCL)  1.9.1-dev
point_traits.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 "pcl/pcl_macros.h"
46 
47 #include <pcl/PCLPointField.h>
48 #include <boost/mpl/assert.hpp>
49 
50 // This is required for the workaround at line 109
51 #ifdef _MSC_VER
52 #include <Eigen/Core>
53 #include <Eigen/src/StlSupport/details.h>
54 #endif
55 
56 #include <type_traits>
57 
58 namespace pcl
59 {
60  namespace deprecated
61  {
62  /** \class DeprecatedType
63  * \brief A dummy type to aid in template parameter deprecation
64  */
65  struct T {};
66  }
67 
68  namespace fields
69  {
70  // Tag types get put in this namespace
71  }
72 
73  namespace traits
74  {
75  // Metafunction to return enum value representing a type
76  template<typename T> struct asEnum {};
77  template<> struct asEnum<std::int8_t> { static const std::uint8_t value = pcl::PCLPointField::INT8; };
78  template<> struct asEnum<std::uint8_t> { static const std::uint8_t value = pcl::PCLPointField::UINT8; };
79  template<> struct asEnum<std::int16_t> { static const std::uint8_t value = pcl::PCLPointField::INT16; };
80  template<> struct asEnum<std::uint16_t> { static const std::uint8_t value = pcl::PCLPointField::UINT16; };
81  template<> struct asEnum<std::int32_t> { static const std::uint8_t value = pcl::PCLPointField::INT32; };
82  template<> struct asEnum<std::uint32_t> { static const std::uint8_t value = pcl::PCLPointField::UINT32; };
83  template<> struct asEnum<float> { static const std::uint8_t value = pcl::PCLPointField::FLOAT32; };
84  template<> struct asEnum<double> { static const std::uint8_t value = pcl::PCLPointField::FLOAT64; };
85 
86  // Metafunction to return type of enum value
87  template<int> struct asType {};
88  template<> struct asType<pcl::PCLPointField::INT8> { using type = std::int8_t; };
89  template<> struct asType<pcl::PCLPointField::UINT8> { using type = std::uint8_t; };
90  template<> struct asType<pcl::PCLPointField::INT16> { using type = std::int16_t; };
91  template<> struct asType<pcl::PCLPointField::UINT16> { using type = std::uint16_t; };
92  template<> struct asType<pcl::PCLPointField::INT32> { using type = std::int32_t; };
93  template<> struct asType<pcl::PCLPointField::UINT32> { using type = std::uint32_t; };
94  template<> struct asType<pcl::PCLPointField::FLOAT32> { using type = float; };
95  template<> struct asType<pcl::PCLPointField::FLOAT64> { using type = double; };
96 
97  // Metafunction to decompose a type (possibly of array of any number of dimensions) into
98  // its scalar type and total number of elements.
99  template<typename T> struct decomposeArray
100  {
101  using type = std::remove_all_extents_t<T>;
102  static const std::uint32_t value = sizeof (T) / sizeof (type);
103  };
104 
105  // For non-POD point types, this is specialized to return the corresponding POD type.
106  template<typename PointT>
107  struct POD
108  {
109  using type = PointT;
110  };
111 
112 #ifdef _MSC_VER
113 
114  /* Sometimes when calling functions like `copyPoint()` or `copyPointCloud`
115  * without explicitly specifying point types, MSVC deduces them to be e.g.
116  * `Eigen::internal::workaround_msvc_stl_support<pcl::PointXYZ>` instead of
117  * plain `pcl::PointXYZ`. Subsequently these types are passed to meta-
118  * functions like `has_field` or `fieldList` and make them choke. This hack
119  * makes use of the fact that internally `fieldList` always applies `POD` to
120  * its argument type. This specialization therefore allows to unwrap the
121  * contained point type. */
122  template<typename PointT>
123  struct POD<Eigen::internal::workaround_msvc_stl_support<PointT> >
124  {
125  using type = PointT;
126  };
127 
128 #endif
129 
130  // name
131  /* This really only depends on Tag, but we go through some gymnastics to avoid ODR violations.
132  We template it on the point type PointT to avoid ODR violations when registering multiple
133  point types with shared tags.
134  The dummy parameter is so we can partially specialize name on PointT and Tag but leave it
135  templated on dummy. Each specialization declares a static char array containing the tag
136  name. The definition of the static member would conflict when linking multiple translation
137  units that include the point type registration. But when the static member definition is
138  templated (on dummy), we sidestep the ODR issue.
139  */
140  template<class PointT, typename Tag, int dummy = 0>
141  struct name : name<typename POD<PointT>::type, Tag, dummy>
142  {
143  // Contents of specialization:
144  // static const char value[];
145 
146  // Avoid infinite compile-time recursion
147  BOOST_MPL_ASSERT_MSG((!std::is_same<PointT, typename POD<PointT>::type>::value),
148  POINT_TYPE_NOT_PROPERLY_REGISTERED, (PointT&));
149  };
150 
151  // offset
152  template<class PointT, typename Tag>
153  struct offset : offset<typename POD<PointT>::type, Tag>
154  {
155  // Contents of specialization:
156  // static const std::size_t value;
157 
158  // Avoid infinite compile-time recursion
159  BOOST_MPL_ASSERT_MSG((!std::is_same<PointT, typename POD<PointT>::type>::value),
160  POINT_TYPE_NOT_PROPERLY_REGISTERED, (PointT&));
161  };
162 
163  // datatype
164  template<class PointT, typename Tag>
165  struct datatype : datatype<typename POD<PointT>::type, Tag>
166  {
167  // Contents of specialization:
168  // using type = ...;
169  // static const std::uint8_t value;
170  // static const std::uint32_t size;
171 
172  // Avoid infinite compile-time recursion
173  BOOST_MPL_ASSERT_MSG((!std::is_same<PointT, typename POD<PointT>::type>::value),
174  POINT_TYPE_NOT_PROPERLY_REGISTERED, (PointT&));
175  };
176 
177  // fields
178  template<typename PointT>
179  struct fieldList : fieldList<typename POD<PointT>::type>
180  {
181  // Contents of specialization:
182  // using type = boost::mpl::vector<...>;
183 
184  // Avoid infinite compile-time recursion
185  BOOST_MPL_ASSERT_MSG((!std::is_same<PointT, typename POD<PointT>::type>::value),
186  POINT_TYPE_NOT_PROPERLY_REGISTERED, (PointT&));
187  };
188  } //namespace traits
189 
190  // Return true if the PCLPointField matches the expected name and data type.
191  // Written as a struct to allow partially specializing on Tag.
192  template<typename PointT, typename Tag>
194  {
195  bool operator() (const pcl::PCLPointField& field)
196  {
197  return (field.name == traits::name<PointT, Tag>::value &&
200  field.count == 0 && traits::datatype<PointT, Tag>::size == 1 /* see bug #821 */));
201  }
202  };
203 
204  /** \brief A helper functor that can copy a specific value if the given field exists.
205  *
206  * \note In order to actually copy the value an instance of this functor should be passed
207  * to a pcl::for_each_type loop. See the example below.
208  *
209  * \code
210  * PointInT p;
211  * bool exists;
212  * float value;
213  * using FieldList = typename pcl::traits::fieldList<PointInT>::type;
214  * pcl::for_each_type<FieldList> (pcl::CopyIfFieldExists<PointT, float> (p, "intensity", exists, value));
215  * \endcode
216  */
217  template <typename PointInT, typename OutT>
219  {
221 
222  /** \brief Constructor.
223  * \param[in] pt the input point
224  * \param[in] field the name of the field
225  * \param[out] exists set to true if the field exists, false otherwise
226  * \param[out] value the copied field value
227  */
228  CopyIfFieldExists (const PointInT &pt,
229  const std::string &field,
230  bool &exists,
231  OutT &value)
232  : pt_ (reinterpret_cast<const Pod&>(pt)), name_ (field), exists_ (exists), value_ (value)
233  {
234  exists_ = false;
235  }
236 
237  /** \brief Constructor.
238  * \param[in] pt the input point
239  * \param[in] field the name of the field
240  * \param[out] value the copied field value
241  */
242  CopyIfFieldExists (const PointInT &pt,
243  const std::string &field,
244  OutT &value)
245  : pt_ (reinterpret_cast<const Pod&>(pt)), name_ (field), exists_ (exists_tmp_), value_ (value)
246  {
247  }
248 
249  /** \brief Operator. Data copy happens here. */
250  template <typename Key> inline void
251  operator() ()
252  {
254  {
255  exists_ = true;
257  const std::uint8_t* data_ptr = reinterpret_cast<const std::uint8_t*>(&pt_) + pcl::traits::offset<PointInT, Key>::value;
258  value_ = static_cast<OutT> (*reinterpret_cast<const T*>(data_ptr));
259  }
260  }
261 
262  private:
263  const Pod &pt_;
264  const std::string &name_;
265  bool &exists_;
266  // Bogus entry
267  bool exists_tmp_;
268  OutT &value_;
269  };
270 
271  /** \brief A helper functor that can set a specific value in a field if the field exists.
272  *
273  * \note In order to actually set the value an instance of this functor should be passed
274  * to a pcl::for_each_type loop. See the example below.
275  *
276  * \code
277  * PointT p;
278  * using FieldList = typename pcl::traits::fieldList<PointT>::type;
279  * pcl::for_each_type<FieldList> (pcl::SetIfFieldExists<PointT, float> (p, "intensity", 42.0f));
280  * \endcode
281  */
282  template <typename PointOutT, typename InT>
284  {
286 
287  /** \brief Constructor.
288  * \param[in] pt the input point
289  * \param[in] field the name of the field
290  * \param[out] value the value to set
291  */
292  SetIfFieldExists (PointOutT &pt,
293  const std::string &field,
294  const InT &value)
295  : pt_ (reinterpret_cast<Pod&>(pt)), name_ (field), value_ (value)
296  {
297  }
298 
299  /** \brief Operator. Data copy happens here. */
300  template <typename Key> inline void
301  operator() ()
302  {
304  {
306  std::uint8_t* data_ptr = reinterpret_cast<std::uint8_t*>(&pt_) + pcl::traits::offset<PointOutT, Key>::value;
307  *reinterpret_cast<T*>(data_ptr) = static_cast<T> (value_);
308  }
309  }
310 
311  private:
312  Pod &pt_;
313  const std::string &name_;
314  const InT &value_;
315  };
316 
317  /** \brief Set the value at a specified field in a point
318  * \param[out] pt the point to set the value to
319  * \param[in] field_offset the offset of the field
320  * \param[in] value the value to set
321  */
322  template <typename PointT, typename ValT> inline void
323  setFieldValue (PointT &pt, std::size_t field_offset, const ValT &value)
324  {
325  std::uint8_t* data_ptr = reinterpret_cast<std::uint8_t*>(&pt) + field_offset;
326  *reinterpret_cast<ValT*>(data_ptr) = value;
327  }
328 
329  /** \brief Get the value at a specified field in a point
330  * \param[in] pt the point to get the value from
331  * \param[in] field_offset the offset of the field
332  * \param[out] value the value to retrieve
333  */
334  template <typename PointT, typename ValT> inline void
335  getFieldValue (const PointT &pt, std::size_t field_offset, ValT &value)
336  {
337  const std::uint8_t* data_ptr = reinterpret_cast<const std::uint8_t*>(&pt) + field_offset;
338  value = *reinterpret_cast<const ValT*>(data_ptr);
339  }
340 
341  template <typename ...> using void_t = void; // part of std in c++17
342 
343 #ifdef DOXYGEN_ONLY
344 
345  /**
346  * \brief Tests at compile time if type T has a custom allocator
347  *
348  * \see pcl::make_shared, PCL_MAKE_ALIGNED_OPERATOR_NEW
349  * \tparam T Type of the object to test
350  */
351  template <typename T> struct has_custom_allocator;
352 
353 #else
354 
355  template <typename, typename = void_t<>> struct has_custom_allocator : std::false_type {};
356  template <typename T> struct has_custom_allocator<T, void_t<typename T::_custom_allocator_type_trait>> : std::true_type {};
357 
358 #endif
359 }
A helper functor that can set a specific value in a field if the field exists.
Definition: point_traits.h:283
This file defines compatibility wrappers for low level I/O functions.
Definition: convolution.h:45
SetIfFieldExists(PointOutT &pt, const std::string &field, const InT &value)
Constructor.
Definition: point_traits.h:292
std::remove_all_extents_t< T > type
Definition: point_traits.h:101
Definition: bfgs.h:9
std::uint32_t count
Definition: PCLPointField.h:21
void void_t
Definition: point_traits.h:341
CopyIfFieldExists(const PointInT &pt, const std::string &field, bool &exists, OutT &value)
Constructor.
Definition: point_traits.h:228
CopyIfFieldExists(const PointInT &pt, const std::string &field, OutT &value)
Constructor.
Definition: point_traits.h:242
typename traits::POD< PointOutT >::type Pod
Definition: point_traits.h:285
typename traits::POD< PointInT >::type Pod
Definition: point_traits.h:220
std::string name
Definition: PCLPointField.h:17
Tests at compile time if type T has a custom allocator.
Definition: point_traits.h:351
void setFieldValue(PointT &pt, std::size_t field_offset, const ValT &value)
Set the value at a specified field in a point.
Definition: point_traits.h:323
A point structure representing Euclidean xyz coordinates, and the RGB color.
std::uint8_t datatype
Definition: PCLPointField.h:20
void getFieldValue(const PointT &pt, std::size_t field_offset, ValT &value)
Get the value at a specified field in a point.
Definition: point_traits.h:335
Defines all the PCL and non-PCL macros used.
A helper functor that can copy a specific value if the given field exists.
Definition: point_traits.h:218