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