Point Cloud Library (PCL)  1.7.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 namespace pcl
57 {
58 
59  namespace fields
60  {
61  // Tag types get put in this namespace
62  }
63 
64  namespace traits
65  {
66  // Metafunction to return enum value representing a type
67  template<typename T> struct asEnum {};
68  template<> struct asEnum<int8_t> { static const uint8_t value = pcl::PCLPointField::INT8; };
69  template<> struct asEnum<uint8_t> { static const uint8_t value = pcl::PCLPointField::UINT8; };
70  template<> struct asEnum<int16_t> { static const uint8_t value = pcl::PCLPointField::INT16; };
71  template<> struct asEnum<uint16_t> { static const uint8_t value = pcl::PCLPointField::UINT16; };
72  template<> struct asEnum<int32_t> { static const uint8_t value = pcl::PCLPointField::INT32; };
73  template<> struct asEnum<uint32_t> { static const uint8_t value = pcl::PCLPointField::UINT32; };
74  template<> struct asEnum<float> { static const uint8_t value = pcl::PCLPointField::FLOAT32; };
75  template<> struct asEnum<double> { static const uint8_t value = pcl::PCLPointField::FLOAT64; };
76 
77  // Metafunction to return type of enum value
78  template<int> struct asType {};
79  template<> struct asType<pcl::PCLPointField::INT8> { typedef int8_t type; };
80  template<> struct asType<pcl::PCLPointField::UINT8> { typedef uint8_t type; };
81  template<> struct asType<pcl::PCLPointField::INT16> { typedef int16_t type; };
82  template<> struct asType<pcl::PCLPointField::UINT16> { typedef uint16_t type; };
83  template<> struct asType<pcl::PCLPointField::INT32> { typedef int32_t type; };
84  template<> struct asType<pcl::PCLPointField::UINT32> { typedef uint32_t type; };
85  template<> struct asType<pcl::PCLPointField::FLOAT32> { typedef float type; };
86  template<> struct asType<pcl::PCLPointField::FLOAT64> { typedef double type; };
87 
88  // Metafunction to decompose a type (possibly of array of any number of dimensions) into
89  // its scalar type and total number of elements.
90  template<typename T> struct decomposeArray
91  {
92  typedef typename boost::remove_all_extents<T>::type type;
93  static const uint32_t value = sizeof (T) / sizeof (type);
94  };
95 
96  // For non-POD point types, this is specialized to return the corresponding POD type.
97  template<typename PointT>
98  struct POD
99  {
100  typedef PointT type;
101  };
102 
103  // name
104  /* This really only depends on Tag, but we go through some gymnastics to avoid ODR violations.
105  We template it on the point type PointT to avoid ODR violations when registering multiple
106  point types with shared tags.
107  The dummy parameter is so we can partially specialize name on PointT and Tag but leave it
108  templated on dummy. Each specialization declares a static char array containing the tag
109  name. The definition of the static member would conflict when linking multiple translation
110  units that include the point type registration. But when the static member definition is
111  templated (on dummy), we sidestep the ODR issue.
112  */
113  template<class PointT, typename Tag, int dummy = 0>
114  struct name : name<typename POD<PointT>::type, Tag, dummy>
115  {
116  // Contents of specialization:
117  // static const char value[];
118 
119  // Avoid infinite compile-time recursion
120  BOOST_MPL_ASSERT_MSG((!boost::is_same<PointT, typename POD<PointT>::type>::value),
121  POINT_TYPE_NOT_PROPERLY_REGISTERED, (PointT&));
122  };
123 
124  // offset
125  template<class PointT, typename Tag>
126  struct offset : offset<typename POD<PointT>::type, Tag>
127  {
128  // Contents of specialization:
129  // static const size_t value;
130 
131  // Avoid infinite compile-time recursion
132  BOOST_MPL_ASSERT_MSG((!boost::is_same<PointT, typename POD<PointT>::type>::value),
133  POINT_TYPE_NOT_PROPERLY_REGISTERED, (PointT&));
134  };
135 
136  // datatype
137  template<class PointT, typename Tag>
138  struct datatype : datatype<typename POD<PointT>::type, Tag>
139  {
140  // Contents of specialization:
141  // typedef ... type;
142  // static const uint8_t value;
143  // static const uint32_t size;
144 
145  // Avoid infinite compile-time recursion
146  BOOST_MPL_ASSERT_MSG((!boost::is_same<PointT, typename POD<PointT>::type>::value),
147  POINT_TYPE_NOT_PROPERLY_REGISTERED, (PointT&));
148  };
149 
150  // fields
151  template<typename PointT>
152  struct fieldList : fieldList<typename POD<PointT>::type>
153  {
154  // Contents of specialization:
155  // typedef boost::mpl::vector<...> type;
156 
157  // Avoid infinite compile-time recursion
158  BOOST_MPL_ASSERT_MSG((!boost::is_same<PointT, typename POD<PointT>::type>::value),
159  POINT_TYPE_NOT_PROPERLY_REGISTERED, (PointT&));
160  };
161 #if PCL_LINEAR_VERSION(__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__) == PCL_LINEAR_VERSION(4,4,3)
162  /*
163  At least on GCC 4.4.3, but not later versions, some valid usages of the above traits for
164  non-POD (but registered) point types fail with:
165  error: ‘!(bool)mpl_::bool_<false>::value’ is not a valid template argument for type ‘bool’ because it is a non-constant expression
166 
167  "Priming the pump" with the trivial assertion below somehow fixes the problem...
168  */
169  //BOOST_MPL_ASSERT_MSG((!bool (mpl_::bool_<false>::value)), WTF_GCC443, (bool));
170  BOOST_MPL_ASSERT_MSG((!bool (boost::mpl::bool_<false>::value)), WTF_GCC443, (bool));
171 #endif
172  } //namespace traits
173 
174  // Return true if the PCLPointField matches the expected name and data type.
175  // Written as a struct to allow partially specializing on Tag.
176  template<typename PointT, typename Tag>
178  {
179  bool operator() (const pcl::PCLPointField& field)
180  {
181  return (field.name == traits::name<PointT, Tag>::value &&
184  field.count == 0 && traits::datatype<PointT, Tag>::size == 1 /* see bug #821 */));
185  }
186  };
187 
188  /** \brief A helper functor that can copy a specific value if the given field exists. */
189  template <typename PointInT, typename OutT>
191  {
193 
194  /** \brief Constructor.
195  * \param[in] pt the input point
196  * \param[in] field the name of the field
197  * \param[out] exists set to true if the field exists, false otherwise
198  * \param[out] value the copied field value
199  */
200  CopyIfFieldExists (const PointInT &pt,
201  const std::string &field,
202  bool &exists,
203  OutT &value)
204  : pt_ (reinterpret_cast<const Pod&>(pt)), name_ (field), exists_ (exists), value_ (value)
205  {
206  exists_ = false;
207  }
208 
209  /** \brief Constructor.
210  * \param[in] pt the input point
211  * \param[in] field the name of the field
212  * \param[out] value the copied field value
213  */
214  CopyIfFieldExists (const PointInT &pt,
215  const std::string &field,
216  OutT &value)
217  : pt_ (reinterpret_cast<const Pod&>(pt)), name_ (field), exists_ (exists_tmp_), value_ (value)
218  {
219  }
220 
221  /** \brief Operator. Data copy happens here. */
222  template <typename Key> inline void
224  {
226  {
227  exists_ = true;
229  const uint8_t* data_ptr = reinterpret_cast<const uint8_t*>(&pt_) + pcl::traits::offset<PointInT, Key>::value;
230  value_ = static_cast<OutT> (*reinterpret_cast<const T*>(data_ptr));
231  }
232  }
233 
234  private:
235  const Pod &pt_;
236  const std::string &name_;
237  bool &exists_;
238  // Bogus entry
239  bool exists_tmp_;
240  OutT &value_;
241  };
242 
243  /** \brief A helper functor that can set a specific value in a field if the field exists. */
244  template <typename PointOutT, typename InT>
246  {
248 
249  /** \brief Constructor.
250  * \param[in] pt the input point
251  * \param[in] field the name of the field
252  * \param[out] value the value to set
253  */
254  SetIfFieldExists (PointOutT &pt,
255  const std::string &field,
256  const InT &value)
257  : pt_ (reinterpret_cast<Pod&>(pt)), name_ (field), value_ (value)
258  {
259  }
260 
261  /** \brief Operator. Data copy happens here. */
262  template <typename Key> inline void
264  {
266  {
268  uint8_t* data_ptr = reinterpret_cast<uint8_t*>(&pt_) + pcl::traits::offset<PointOutT, Key>::value;
269  *reinterpret_cast<T*>(data_ptr) = static_cast<T> (value_);
270  }
271  }
272 
273  private:
274  Pod &pt_;
275  const std::string &name_;
276  const InT &value_;
277  };
278 
279  /** \brief Set the value at a specified field in a point
280  * \param[out] pt the point to set the value to
281  * \param[in] field_offset the offset of the field
282  * \param[in] value the value to set
283  */
284  template <typename PointT, typename ValT> inline void
285  setFieldValue (PointT &pt, size_t field_offset, const ValT &value)
286  {
287  uint8_t* data_ptr = reinterpret_cast<uint8_t*>(&pt) + field_offset;
288  *reinterpret_cast<ValT*>(data_ptr) = value;
289  }
290 
291  /** \brief Get the value at a specified field in a point
292  * \param[in] pt the point to get the value from
293  * \param[in] field_offset the offset of the field
294  * \param[out] value the value to retreive
295  */
296  template <typename PointT, typename ValT> inline void
297  getFieldValue (const PointT &pt, size_t field_offset, ValT &value)
298  {
299  const uint8_t* data_ptr = reinterpret_cast<const uint8_t*>(&pt) + field_offset;
300  value = *reinterpret_cast<const ValT*>(data_ptr);
301  }
302 }
303 
304 #endif //#ifndef PCL_POINT_TRAITS_H_