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