Point Cloud Library (PCL)  1.7.1
register_point_struct.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  * $Id$
38  *
39  */
40 
41 #ifndef PCL_REGISTER_POINT_STRUCT_H_
42 #define PCL_REGISTER_POINT_STRUCT_H_
43 
44 #ifdef __GNUC__
45 #pragma GCC system_header
46 #endif
47 
48 #if defined _MSC_VER
49  #pragma warning (push, 2)
50  // 4244 : conversion from 'type1' to 'type2', possible loss of data
51  #pragma warning (disable: 4244)
52 #endif
53 
54 #include <pcl/pcl_macros.h>
55 #include <pcl/point_traits.h>
56 #include <boost/mpl/vector.hpp>
57 #include <boost/preprocessor/seq/enum.hpp>
58 #include <boost/preprocessor/seq/for_each.hpp>
59 #include <boost/preprocessor/seq/transform.hpp>
60 #include <boost/preprocessor/cat.hpp>
61 #include <boost/preprocessor/comparison.hpp>
62 #include <boost/utility.hpp>
63 //https://bugreports.qt-project.org/browse/QTBUG-22829
64 #ifndef Q_MOC_RUN
65 #include <boost/type_traits.hpp>
66 #endif
67 #include <stddef.h> //offsetof
68 
69 // Must be used in global namespace with name fully qualified
70 #define POINT_CLOUD_REGISTER_POINT_STRUCT(name, fseq) \
71  POINT_CLOUD_REGISTER_POINT_STRUCT_I(name, \
72  BOOST_PP_CAT(POINT_CLOUD_REGISTER_POINT_STRUCT_X fseq, 0)) \
73  /***/
74 
75 #define POINT_CLOUD_REGISTER_POINT_WRAPPER(wrapper, pod) \
76  BOOST_MPL_ASSERT_MSG(sizeof(wrapper) == sizeof(pod), POINT_WRAPPER_AND_POD_TYPES_HAVE_DIFFERENT_SIZES, (wrapper&, pod&)); \
77  namespace pcl { \
78  namespace traits { \
79  template<> struct POD<wrapper> { typedef pod type; }; \
80  } \
81  } \
82  /***/
83 
84 // These macros help transform the unusual data structure (type, name, tag)(type, name, tag)...
85 // into a proper preprocessor sequence of 3-tuples ((type, name, tag))((type, name, tag))...
86 #define POINT_CLOUD_REGISTER_POINT_STRUCT_X(type, name, tag) \
87  ((type, name, tag)) POINT_CLOUD_REGISTER_POINT_STRUCT_Y
88 #define POINT_CLOUD_REGISTER_POINT_STRUCT_Y(type, name, tag) \
89  ((type, name, tag)) POINT_CLOUD_REGISTER_POINT_STRUCT_X
90 #define POINT_CLOUD_REGISTER_POINT_STRUCT_X0
91 #define POINT_CLOUD_REGISTER_POINT_STRUCT_Y0
92 
93 namespace pcl
94 {
95  namespace traits
96  {
97  template<typename T> inline
98  typename boost::disable_if_c<boost::is_array<T>::value>::type
99  plus (T &l, const T &r)
100  {
101  l += r;
102  }
103 
104  template<typename T> inline
105  typename boost::enable_if_c<boost::is_array<T>::value>::type
106  plus (typename boost::remove_const<T>::type &l, const T &r)
107  {
108  typedef typename boost::remove_all_extents<T>::type type;
109  static const uint32_t count = sizeof (T) / sizeof (type);
110  for (int i = 0; i < count; ++i)
111  l[i] += r[i];
112  }
113 
114  template<typename T1, typename T2> inline
115  typename boost::disable_if_c<boost::is_array<T1>::value>::type
116  plusscalar (T1 &p, const T2 &scalar)
117  {
118  p += scalar;
119  }
120 
121  template<typename T1, typename T2> inline
122  typename boost::enable_if_c<boost::is_array<T1>::value>::type
123  plusscalar (T1 &p, const T2 &scalar)
124  {
125  typedef typename boost::remove_all_extents<T1>::type type;
126  static const uint32_t count = sizeof (T1) / sizeof (type);
127  for (int i = 0; i < count; ++i)
128  p[i] += scalar;
129  }
130 
131  template<typename T> inline
132  typename boost::disable_if_c<boost::is_array<T>::value>::type
133  minus (T &l, const T &r)
134  {
135  l -= r;
136  }
137 
138  template<typename T> inline
139  typename boost::enable_if_c<boost::is_array<T>::value>::type
140  minus (typename boost::remove_const<T>::type &l, const T &r)
141  {
142  typedef typename boost::remove_all_extents<T>::type type;
143  static const uint32_t count = sizeof (T) / sizeof (type);
144  for (int i = 0; i < count; ++i)
145  l[i] -= r[i];
146  }
147 
148  template<typename T1, typename T2> inline
149  typename boost::disable_if_c<boost::is_array<T1>::value>::type
150  minusscalar (T1 &p, const T2 &scalar)
151  {
152  p -= scalar;
153  }
154 
155  template<typename T1, typename T2> inline
156  typename boost::enable_if_c<boost::is_array<T1>::value>::type
157  minusscalar (T1 &p, const T2 &scalar)
158  {
159  typedef typename boost::remove_all_extents<T1>::type type;
160  static const uint32_t count = sizeof (T1) / sizeof (type);
161  for (int i = 0; i < count; ++i)
162  p[i] -= scalar;
163  }
164 
165  template<typename T1, typename T2> inline
166  typename boost::disable_if_c<boost::is_array<T1>::value>::type
167  mulscalar (T1 &p, const T2 &scalar)
168  {
169  p *= scalar;
170  }
171 
172  template<typename T1, typename T2> inline
173  typename boost::enable_if_c<boost::is_array<T1>::value>::type
174  mulscalar (T1 &p, const T2 &scalar)
175  {
176  typedef typename boost::remove_all_extents<T1>::type type;
177  static const uint32_t count = sizeof (T1) / sizeof (type);
178  for (int i = 0; i < count; ++i)
179  p[i] *= scalar;
180  }
181 
182  template<typename T1, typename T2> inline
183  typename boost::disable_if_c<boost::is_array<T1>::value>::type
184  divscalar (T1 &p, const T2 &scalar)
185  {
186  p /= scalar;
187  }
188 
189  template<typename T1, typename T2> inline
190  typename boost::enable_if_c<boost::is_array<T1>::value>::type
191  divscalar (T1 &p, const T2 &scalar)
192  {
193  typedef typename boost::remove_all_extents<T1>::type type;
194  static const uint32_t count = sizeof (T1) / sizeof (type);
195  for (int i = 0; i < count; ++i)
196  p[i] /= scalar;
197  }
198  }
199 }
200 
201 // Point operators
202 #define PCL_PLUSEQ_POINT_TAG(r, data, elem) \
203  pcl::traits::plus (lhs.BOOST_PP_TUPLE_ELEM(3, 1, elem), \
204  rhs.BOOST_PP_TUPLE_ELEM(3, 1, elem)); \
205  /***/
206 
207 #define PCL_PLUSEQSC_POINT_TAG(r, data, elem) \
208  pcl::traits::plusscalar (p.BOOST_PP_TUPLE_ELEM(3, 1, elem), \
209  scalar); \
210  /***/
211  //p.BOOST_PP_TUPLE_ELEM(3, 1, elem) += scalar; \
212 
213 #define PCL_MINUSEQ_POINT_TAG(r, data, elem) \
214  pcl::traits::minus (lhs.BOOST_PP_TUPLE_ELEM(3, 1, elem), \
215  rhs.BOOST_PP_TUPLE_ELEM(3, 1, elem)); \
216  /***/
217 
218 #define PCL_MINUSEQSC_POINT_TAG(r, data, elem) \
219  pcl::traits::minusscalar (p.BOOST_PP_TUPLE_ELEM(3, 1, elem), \
220  scalar); \
221  /***/
222  //p.BOOST_PP_TUPLE_ELEM(3, 1, elem) -= scalar; \
223 
224 #define PCL_MULEQSC_POINT_TAG(r, data, elem) \
225  pcl::traits::mulscalar (p.BOOST_PP_TUPLE_ELEM(3, 1, elem), \
226  scalar); \
227  /***/
228 
229 #define PCL_DIVEQSC_POINT_TAG(r, data, elem) \
230  pcl::traits::divscalar (p.BOOST_PP_TUPLE_ELEM(3, 1, elem), \
231  scalar); \
232  /***/
233 
234 // Construct type traits given full sequence of (type, name, tag) triples
235 // BOOST_MPL_ASSERT_MSG(boost::is_pod<name>::value,
236 // REGISTERED_POINT_TYPE_MUST_BE_PLAIN_OLD_DATA, (name));
237 #define POINT_CLOUD_REGISTER_POINT_STRUCT_I(name, seq) \
238  namespace pcl \
239  { \
240  namespace fields \
241  { \
242  BOOST_PP_SEQ_FOR_EACH(POINT_CLOUD_REGISTER_FIELD_TAG, name, seq) \
243  } \
244  namespace traits \
245  { \
246  BOOST_PP_SEQ_FOR_EACH(POINT_CLOUD_REGISTER_FIELD_NAME, name, seq) \
247  BOOST_PP_SEQ_FOR_EACH(POINT_CLOUD_REGISTER_FIELD_OFFSET, name, seq) \
248  BOOST_PP_SEQ_FOR_EACH(POINT_CLOUD_REGISTER_FIELD_DATATYPE, name, seq) \
249  POINT_CLOUD_REGISTER_POINT_FIELD_LIST(name, POINT_CLOUD_EXTRACT_TAGS(seq)) \
250  } \
251  namespace common \
252  { \
253  inline const name& \
254  operator+= (name& lhs, const name& rhs) \
255  { \
256  BOOST_PP_SEQ_FOR_EACH(PCL_PLUSEQ_POINT_TAG, _, seq) \
257  return (lhs); \
258  } \
259  inline const name& \
260  operator+= (name& p, const float& scalar) \
261  { \
262  BOOST_PP_SEQ_FOR_EACH(PCL_PLUSEQSC_POINT_TAG, _, seq) \
263  return (p); \
264  } \
265  inline const name operator+ (const name& lhs, const name& rhs) \
266  { name result = lhs; result += rhs; return (result); } \
267  inline const name operator+ (const float& scalar, const name& p) \
268  { name result = p; result += scalar; return (result); } \
269  inline const name operator+ (const name& p, const float& scalar) \
270  { name result = p; result += scalar; return (result); } \
271  inline const name& \
272  operator-= (name& lhs, const name& rhs) \
273  { \
274  BOOST_PP_SEQ_FOR_EACH(PCL_MINUSEQ_POINT_TAG, _, seq) \
275  return (lhs); \
276  } \
277  inline const name& \
278  operator-= (name& p, const float& scalar) \
279  { \
280  BOOST_PP_SEQ_FOR_EACH(PCL_MINUSEQSC_POINT_TAG, _, seq) \
281  return (p); \
282  } \
283  inline const name operator- (const name& lhs, const name& rhs) \
284  { name result = lhs; result -= rhs; return (result); } \
285  inline const name operator- (const float& scalar, const name& p) \
286  { name result = p; result -= scalar; return (result); } \
287  inline const name operator- (const name& p, const float& scalar) \
288  { name result = p; result -= scalar; return (result); } \
289  inline const name& \
290  operator*= (name& p, const float& scalar) \
291  { \
292  BOOST_PP_SEQ_FOR_EACH(PCL_MULEQSC_POINT_TAG, _, seq) \
293  return (p); \
294  } \
295  inline const name operator* (const float& scalar, const name& p) \
296  { name result = p; result *= scalar; return (result); } \
297  inline const name operator* (const name& p, const float& scalar) \
298  { name result = p; result *= scalar; return (result); } \
299  inline const name& \
300  operator/= (name& p, const float& scalar) \
301  { \
302  BOOST_PP_SEQ_FOR_EACH(PCL_DIVEQSC_POINT_TAG, _, seq) \
303  return (p); \
304  } \
305  inline const name operator/ (const float& scalar, const name& p) \
306  { name result = p; result /= scalar; return (result); } \
307  inline const name operator/ (const name& p, const float& scalar) \
308  { name result = p; result /= scalar; return (result); } \
309  } \
310  } \
311  /***/
312 
313 #define POINT_CLOUD_REGISTER_FIELD_TAG(r, name, elem) \
314  struct BOOST_PP_TUPLE_ELEM(3, 2, elem); \
315  /***/
316 
317 #define POINT_CLOUD_REGISTER_FIELD_NAME(r, point, elem) \
318  template<int dummy> \
319  struct name<point, pcl::fields::BOOST_PP_TUPLE_ELEM(3, 2, elem), dummy> \
320  { \
321  static const char value[]; \
322  }; \
323  \
324  template<int dummy> \
325  const char name<point, \
326  pcl::fields::BOOST_PP_TUPLE_ELEM(3, 2, elem), \
327  dummy>::value[] = \
328  BOOST_PP_STRINGIZE(BOOST_PP_TUPLE_ELEM(3, 2, elem)); \
329  /***/
330 
331 #define POINT_CLOUD_REGISTER_FIELD_OFFSET(r, name, elem) \
332  template<> struct offset<name, pcl::fields::BOOST_PP_TUPLE_ELEM(3, 2, elem)> \
333  { \
334  static const size_t value = offsetof(name, BOOST_PP_TUPLE_ELEM(3, 1, elem)); \
335  }; \
336  /***/
337 
338 // \note: the mpl::identity weirdness is to support array types without requiring the
339 // user to wrap them. The basic problem is:
340 // typedef float[81] type; // SYNTAX ERROR!
341 // typedef float type[81]; // OK, can now use "type" as a synonym for float[81]
342 #define POINT_CLOUD_REGISTER_FIELD_DATATYPE(r, name, elem) \
343  template<> struct datatype<name, pcl::fields::BOOST_PP_TUPLE_ELEM(3, 2, elem)> \
344  { \
345  typedef boost::mpl::identity<BOOST_PP_TUPLE_ELEM(3, 0, elem)>::type type; \
346  typedef decomposeArray<type> decomposed; \
347  static const uint8_t value = asEnum<decomposed::type>::value; \
348  static const uint32_t size = decomposed::value; \
349  }; \
350  /***/
351 
352 #define POINT_CLOUD_TAG_OP(s, data, elem) pcl::fields::BOOST_PP_TUPLE_ELEM(3, 2, elem)
353 
354 #define POINT_CLOUD_EXTRACT_TAGS(seq) BOOST_PP_SEQ_TRANSFORM(POINT_CLOUD_TAG_OP, _, seq)
355 
356 #define POINT_CLOUD_REGISTER_POINT_FIELD_LIST(name, seq) \
357  template<> struct fieldList<name> \
358  { \
359  typedef boost::mpl::vector<BOOST_PP_SEQ_ENUM(seq)> type; \
360  }; \
361  /***/
362 
363 #if defined _MSC_VER
364  #pragma warning (pop)
365 #endif
366 
367 #endif //#ifndef PCL_REGISTER_POINT_STRUCT_H_
boost::disable_if_c< boost::is_array< T >::value >::type plus(T &l, const T &r)
boost::disable_if_c< boost::is_array< T1 >::value >::type divscalar(T1 &p, const T2 &scalar)
boost::disable_if_c< boost::is_array< T >::value >::type minus(T &l, const T &r)
boost::disable_if_c< boost::is_array< T1 >::value >::type minusscalar(T1 &p, const T2 &scalar)
boost::disable_if_c< boost::is_array< T1 >::value >::type mulscalar(T1 &p, const T2 &scalar)
boost::disable_if_c< boost::is_array< T1 >::value >::type plusscalar(T1 &p, const T2 &scalar)