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/type_traits/remove_all_extents.hpp>
49 #include <boost/type_traits/is_same.hpp>
50 #include <boost/mpl/assert.hpp>
51 
52 // This is required for the workaround at line 109
53 #ifdef _MSC_VER
54 #include <Eigen/Core>
55 #include <Eigen/src/StlSupport/details.h>
56 #endif
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<int8_t> { static const uint8_t value = pcl::PCLPointField::INT8; };
78  template<> struct asEnum<uint8_t> { static const uint8_t value = pcl::PCLPointField::UINT8; };
79  template<> struct asEnum<int16_t> { static const uint8_t value = pcl::PCLPointField::INT16; };
80  template<> struct asEnum<uint16_t> { static const uint8_t value = pcl::PCLPointField::UINT16; };
81  template<> struct asEnum<int32_t> { static const uint8_t value = pcl::PCLPointField::INT32; };
82  template<> struct asEnum<uint32_t> { static const uint8_t value = pcl::PCLPointField::UINT32; };
83  template<> struct asEnum<float> { static const uint8_t value = pcl::PCLPointField::FLOAT32; };
84  template<> struct asEnum<double> { static const 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> { typedef int8_t type; };
89  template<> struct asType<pcl::PCLPointField::UINT8> { typedef uint8_t type; };
90  template<> struct asType<pcl::PCLPointField::INT16> { typedef int16_t type; };
91  template<> struct asType<pcl::PCLPointField::UINT16> { typedef uint16_t type; };
92  template<> struct asType<pcl::PCLPointField::INT32> { typedef int32_t type; };
93  template<> struct asType<pcl::PCLPointField::UINT32> { typedef uint32_t type; };
94  template<> struct asType<pcl::PCLPointField::FLOAT32> { typedef float type; };
95  template<> struct asType<pcl::PCLPointField::FLOAT64> { typedef double type; };
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  typedef typename boost::remove_all_extents<T>::type type;
102  static const 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  typedef PointT type;
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  typedef PointT type;
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((!boost::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 size_t value;
157 
158  // Avoid infinite compile-time recursion
159  BOOST_MPL_ASSERT_MSG((!boost::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  // typedef ... type;
169  // static const uint8_t value;
170  // static const uint32_t size;
171 
172  // Avoid infinite compile-time recursion
173  BOOST_MPL_ASSERT_MSG((!boost::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  // typedef boost::mpl::vector<...> type;
183 
184  // Avoid infinite compile-time recursion
185  BOOST_MPL_ASSERT_MSG((!boost::is_same<PointT, typename POD<PointT>::type>::value),
186  POINT_TYPE_NOT_PROPERLY_REGISTERED, (PointT&));
187  };
188 #if PCL_LINEAR_VERSION(__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__) == PCL_LINEAR_VERSION(4,4,3)
189  /*
190  At least on GCC 4.4.3, but not later versions, some valid usages of the above traits for
191  non-POD (but registered) point types fail with:
192  error: ‘!(bool)mpl_::bool_<false>::value’ is not a valid template argument for type ‘bool’ because it is a non-constant expression
193 
194  "Priming the pump" with the trivial assertion below somehow fixes the problem...
195  */
196  //BOOST_MPL_ASSERT_MSG((!bool (mpl_::bool_<false>::value)), WTF_GCC443, (bool));
197  BOOST_MPL_ASSERT_MSG((!bool (boost::mpl::bool_<false>::value)), WTF_GCC443, (bool));
198 #endif
199  } //namespace traits
200 
201  // Return true if the PCLPointField matches the expected name and data type.
202  // Written as a struct to allow partially specializing on Tag.
203  template<typename PointT, typename Tag>
205  {
206  bool operator() (const pcl::PCLPointField& field)
207  {
208  return (field.name == traits::name<PointT, Tag>::value &&
211  field.count == 0 && traits::datatype<PointT, Tag>::size == 1 /* see bug #821 */));
212  }
213  };
214 
215  /** \brief A helper functor that can copy a specific value if the given field exists.
216  *
217  * \note In order to actually copy the value an instance of this functor should be passed
218  * to a pcl::for_each_type loop. See the example below.
219  *
220  * \code
221  * PointInT p;
222  * bool exists;
223  * float value;
224  * typedef typename pcl::traits::fieldList<PointInT>::type FieldList;
225  * pcl::for_each_type<FieldList> (pcl::CopyIfFieldExists<PointT, float> (p, "intensity", exists, value));
226  * \endcode
227  */
228  template <typename PointInT, typename OutT>
230  {
232 
233  /** \brief Constructor.
234  * \param[in] pt the input point
235  * \param[in] field the name of the field
236  * \param[out] exists set to true if the field exists, false otherwise
237  * \param[out] value the copied field value
238  */
239  CopyIfFieldExists (const PointInT &pt,
240  const std::string &field,
241  bool &exists,
242  OutT &value)
243  : pt_ (reinterpret_cast<const Pod&>(pt)), name_ (field), exists_ (exists), value_ (value)
244  {
245  exists_ = false;
246  }
247 
248  /** \brief Constructor.
249  * \param[in] pt the input point
250  * \param[in] field the name of the field
251  * \param[out] value the copied field value
252  */
253  CopyIfFieldExists (const PointInT &pt,
254  const std::string &field,
255  OutT &value)
256  : pt_ (reinterpret_cast<const Pod&>(pt)), name_ (field), exists_ (exists_tmp_), value_ (value)
257  {
258  }
259 
260  /** \brief Operator. Data copy happens here. */
261  template <typename Key> inline void
262  operator() ()
263  {
265  {
266  exists_ = true;
268  const uint8_t* data_ptr = reinterpret_cast<const uint8_t*>(&pt_) + pcl::traits::offset<PointInT, Key>::value;
269  value_ = static_cast<OutT> (*reinterpret_cast<const T*>(data_ptr));
270  }
271  }
272 
273  private:
274  const Pod &pt_;
275  const std::string &name_;
276  bool &exists_;
277  // Bogus entry
278  bool exists_tmp_;
279  OutT &value_;
280  };
281 
282  /** \brief A helper functor that can set a specific value in a field if the field exists.
283  *
284  * \note In order to actually set the value an instance of this functor should be passed
285  * to a pcl::for_each_type loop. See the example below.
286  *
287  * \code
288  * PointT p;
289  * typedef typename pcl::traits::fieldList<PointT>::type FieldList;
290  * pcl::for_each_type<FieldList> (pcl::SetIfFieldExists<PointT, float> (p, "intensity", 42.0f));
291  * \endcode
292  */
293  template <typename PointOutT, typename InT>
295  {
297 
298  /** \brief Constructor.
299  * \param[in] pt the input point
300  * \param[in] field the name of the field
301  * \param[out] value the value to set
302  */
303  SetIfFieldExists (PointOutT &pt,
304  const std::string &field,
305  const InT &value)
306  : pt_ (reinterpret_cast<Pod&>(pt)), name_ (field), value_ (value)
307  {
308  }
309 
310  /** \brief Operator. Data copy happens here. */
311  template <typename Key> inline void
312  operator() ()
313  {
315  {
317  uint8_t* data_ptr = reinterpret_cast<uint8_t*>(&pt_) + pcl::traits::offset<PointOutT, Key>::value;
318  *reinterpret_cast<T*>(data_ptr) = static_cast<T> (value_);
319  }
320  }
321 
322  private:
323  Pod &pt_;
324  const std::string &name_;
325  const InT &value_;
326  };
327 
328  /** \brief Set the value at a specified field in a point
329  * \param[out] pt the point to set the value to
330  * \param[in] field_offset the offset of the field
331  * \param[in] value the value to set
332  */
333  template <typename PointT, typename ValT> inline void
334  setFieldValue (PointT &pt, size_t field_offset, const ValT &value)
335  {
336  uint8_t* data_ptr = reinterpret_cast<uint8_t*>(&pt) + field_offset;
337  *reinterpret_cast<ValT*>(data_ptr) = value;
338  }
339 
340  /** \brief Get the value at a specified field in a point
341  * \param[in] pt the point to get the value from
342  * \param[in] field_offset the offset of the field
343  * \param[out] value the value to retrieve
344  */
345  template <typename PointT, typename ValT> inline void
346  getFieldValue (const PointT &pt, size_t field_offset, ValT &value)
347  {
348  const uint8_t* data_ptr = reinterpret_cast<const uint8_t*>(&pt) + field_offset;
349  value = *reinterpret_cast<const ValT*>(data_ptr);
350  }
351 }
A helper functor that can set a specific value in a field if the field exists.
Definition: point_traits.h:294
boost::remove_all_extents< T >::type type
Definition: point_traits.h:101
This file defines compatibility wrappers for low level I/O functions.
Definition: convolution.h:44
SetIfFieldExists(PointOutT &pt, const std::string &field, const InT &value)
Constructor.
Definition: point_traits.h:303
Definition: bfgs.h:9
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:334
pcl::uint32_t count
Definition: PCLPointField.h:24
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:346
CopyIfFieldExists(const PointInT &pt, const std::string &field, bool &exists, OutT &value)
Constructor.
Definition: point_traits.h:239
CopyIfFieldExists(const PointInT &pt, const std::string &field, OutT &value)
Constructor.
Definition: point_traits.h:253
pcl::uint8_t datatype
Definition: PCLPointField.h:23
std::string name
Definition: PCLPointField.h:20
traits::POD< PointOutT >::type Pod
Definition: point_traits.h:296
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:229
traits::POD< PointInT >::type Pod
Definition: point_traits.h:231