Point Cloud Library (PCL)  1.6.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
point_traits.h
Go to the documentation of this file.
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  *
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * * Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  * * Redistributions in binary form must reproduce the above
16  * copyright notice, this list of conditions and the following
17  * disclaimer in the documentation and/or other materials provided
18  * with the distribution.
19  * * Neither the name of Willow Garage, Inc. nor the names of its
20  * contributors may be used to endorse or promote products derived
21  * from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  *
36  * $Id: point_traits.h 5286 2012-03-25 01:43:57Z nizar $
37  *
38  */
39 
40 #ifndef PCL_POINT_TRAITS_H_
41 #define PCL_POINT_TRAITS_H_
42 
43 #include <sensor_msgs/PointField.h>
44 #include <boost/type_traits/remove_all_extents.hpp>
45 #include <boost/type_traits/is_same.hpp>
46 #include <boost/mpl/assert.hpp>
47 #include <boost/mpl/bool.hpp>
48 
49 // We're doing a lot of black magic with Boost here, so disable warnings in Maintainer mode, as we will never
50 // be able to fix them anyway
51 #ifdef BUILD_Maintainer
52 # if defined __GNUC__
53 # include <features.h>
54 # if __GNUC_PREREQ(4, 3)
55 # pragma GCC diagnostic ignored "-Weffc++"
56 # pragma GCC diagnostic ignored "-pedantic"
57 # else
58 # pragma GCC system_header
59 # endif
60 # elif defined _MSC_VER
61 # pragma warning(push, 1)
62 # endif
63 #endif
64 
65 namespace pcl
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 = sensor_msgs::PointField::INT8; };
78  template<> struct asEnum<uint8_t> { static const uint8_t value = sensor_msgs::PointField::UINT8; };
79  template<> struct asEnum<int16_t> { static const uint8_t value = sensor_msgs::PointField::INT16; };
80  template<> struct asEnum<uint16_t> { static const uint8_t value = sensor_msgs::PointField::UINT16; };
81  template<> struct asEnum<int32_t> { static const uint8_t value = sensor_msgs::PointField::INT32; };
82  template<> struct asEnum<uint32_t> { static const uint8_t value = sensor_msgs::PointField::UINT32; };
83  template<> struct asEnum<float> { static const uint8_t value = sensor_msgs::PointField::FLOAT32; };
84  template<> struct asEnum<double> { static const uint8_t value = sensor_msgs::PointField::FLOAT64; };
85 
86  // Metafunction to return type of enum value
87  template<int> struct asType {};
88  template<> struct asType<sensor_msgs::PointField::INT8> { typedef int8_t type; };
89  template<> struct asType<sensor_msgs::PointField::UINT8> { typedef uint8_t type; };
90  template<> struct asType<sensor_msgs::PointField::INT16> { typedef int16_t type; };
91  template<> struct asType<sensor_msgs::PointField::UINT16> { typedef uint16_t type; };
92  template<> struct asType<sensor_msgs::PointField::INT32> { typedef int32_t type; };
93  template<> struct asType<sensor_msgs::PointField::UINT32> { typedef uint32_t type; };
94  template<> struct asType<sensor_msgs::PointField::FLOAT32> { typedef float type; };
95  template<> struct asType<sensor_msgs::PointField::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  // name
113  /* This really only depends on Tag, but we go through some gymnastics to avoid ODR violations.
114  We template it on the point type PointT to avoid ODR violations when registering multiple
115  point types with shared tags.
116  The dummy parameter is so we can partially specialize name on PointT and Tag but leave it
117  templated on dummy. Each specialization declares a static char array containing the tag
118  name. The definition of the static member would conflict when linking multiple translation
119  units that include the point type registration. But when the static member definition is
120  templated (on dummy), we sidestep the ODR issue.
121  */
122  template<class PointT, typename Tag, int dummy = 0>
123  struct name : name<typename POD<PointT>::type, Tag, dummy>
124  {
125  // Contents of specialization:
126  // static const char value[];
127 
128  // Avoid infinite compile-time recursion
129  BOOST_MPL_ASSERT_MSG((!boost::is_same<PointT, typename POD<PointT>::type>::value),
130  POINT_TYPE_NOT_PROPERLY_REGISTERED, (PointT&));
131  };
132 
133  // offset
134  template<class PointT, typename Tag>
135  struct offset : offset<typename POD<PointT>::type, Tag>
136  {
137  // Contents of specialization:
138  // static const size_t value;
139 
140  // Avoid infinite compile-time recursion
141  BOOST_MPL_ASSERT_MSG((!boost::is_same<PointT, typename POD<PointT>::type>::value),
142  POINT_TYPE_NOT_PROPERLY_REGISTERED, (PointT&));
143  };
144 
145  // datatype
146  template<class PointT, typename Tag>
147  struct datatype : datatype<typename POD<PointT>::type, Tag>
148  {
149  // Contents of specialization:
150  // typedef ... type;
151  // static const uint8_t value;
152  // static const uint32_t size;
153 
154  // Avoid infinite compile-time recursion
155  BOOST_MPL_ASSERT_MSG((!boost::is_same<PointT, typename POD<PointT>::type>::value),
156  POINT_TYPE_NOT_PROPERLY_REGISTERED, (PointT&));
157  };
158 
159  // fields
160  template<typename PointT>
161  struct fieldList : fieldList<typename POD<PointT>::type>
162  {
163  // Contents of specialization:
164  // typedef boost::mpl::vector<...> type;
165 
166  // Avoid infinite compile-time recursion
167  BOOST_MPL_ASSERT_MSG((!boost::is_same<PointT, typename POD<PointT>::type>::value),
168  POINT_TYPE_NOT_PROPERLY_REGISTERED, (PointT&));
169  };
170 
171  /*
172  At least on GCC 4.4.3, but not later versions, some valid usages of the above traits for
173  non-POD (but registered) point types fail with:
174  error: ‘!(bool)mpl_::bool_<false>::value’ is not a valid template argument for type ‘bool’ because it is a non-constant expression
175 
176  "Priming the pump" with the trivial assertion below somehow fixes the problem...
177  */
178  //BOOST_MPL_ASSERT_MSG((!bool (mpl_::bool_<false>::value)), WTF_GCC443, (bool));
179  BOOST_MPL_ASSERT_MSG((!bool (boost::mpl::bool_<false>::value)), WTF_GCC443, (bool));
180  } //namespace traits
181 
182  // Return true if the PointField matches the expected name and data type.
183  // Written as a struct to allow partially specializing on Tag.
184  template<typename PointT, typename Tag>
186  {
188  {
189  return (field.name == traits::name<PointT, Tag>::value &&
192  }
193  };
194 
196  template <typename PointInT, typename OutT>
198  {
200 
207  CopyIfFieldExists (const PointInT &pt,
208  const std::string &field,
209  bool &exists,
210  OutT &value)
211  : pt_ (reinterpret_cast<const Pod&>(pt)), name_ (field), exists_ (exists), value_ (value)
212  {
213  exists_ = false;
214  }
215 
221  CopyIfFieldExists (const PointInT &pt,
222  const std::string &field,
223  OutT &value)
224  : pt_ (reinterpret_cast<const Pod&>(pt)), name_ (field), exists_ (exists_tmp_), value_ (value)
225  {
226  }
227 
229  template <typename Key> inline void
231  {
233  {
234  exists_ = true;
236  const uint8_t* data_ptr = reinterpret_cast<const uint8_t*>(&pt_) + pcl::traits::offset<PointInT, Key>::value;
237  value_ = static_cast<OutT> (*reinterpret_cast<const T*>(data_ptr));
238  }
239  }
240 
241  private:
242  const Pod &pt_;
243  const std::string &name_;
244  bool &exists_;
245  // Bogus entry
246  bool exists_tmp_;
247  OutT &value_;
248  };
249 
251  template <typename PointOutT, typename InT>
253  {
255 
261  SetIfFieldExists (PointOutT &pt,
262  const std::string &field,
263  const InT &value)
264  : pt_ (reinterpret_cast<Pod&>(pt)), name_ (field), value_ (value)
265  {
266  }
267 
269  template <typename Key> inline void
271  {
273  {
275  uint8_t* data_ptr = reinterpret_cast<uint8_t*>(&pt_) + pcl::traits::offset<PointOutT, Key>::value;
276  *reinterpret_cast<T*>(data_ptr) = static_cast<T> (value_);
277  }
278  }
279 
280  private:
281  Pod &pt_;
282  const std::string &name_;
283  const InT &value_;
284  };
285 }
286 
287 #ifdef BUILD_Maintainer
288 # if defined __GNUC__
289 # if __GNUC_PREREQ(4, 3)
290 # pragma GCC diagnostic warning "-Weffc++"
291 # pragma GCC diagnostic warning "-pedantic"
292 # endif
293 # elif defined _MSC_VER
294 # pragma warning(pop)
295 # endif
296 #endif
297 
298 #endif //#ifndef PCL_POINT_TRAITS_H_