call_with_point_type.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <functional>
4 #include <type_traits>
5 
6 #include <pcl/point_cloud.h>
7 #include <pcl/point_types.h>
8 
10 
11 #include <VisionX/interface/core/DataTypes.h>
12 
13 
14 namespace visionx::tools::detail
15 {
16  /// Base class of functors with return value.
18 
19 
20  template <PointContentType pointContentType>
21  struct PclPointType
22  {
23  using PointT = pcl::PointXYZ;
24  };
25  template <> struct PclPointType<PointContentType::ePoints>
26  {
27  using PointT = pcl::PointXYZ;
28  };
29  template <> struct PclPointType<PointContentType::eIntensity>
30  {
31  using PointT = pcl::PointXYZI;
32  };
33  template <> struct PclPointType<PointContentType::eColoredPoints>
34  {
35  using PointT = pcl::PointXYZRGBA;
36  };
37  template <> struct PclPointType<PointContentType::eLabeledPoints>
38  {
39  using PointT = pcl::PointXYZL;
40  };
41  template <> struct PclPointType<PointContentType::eOrientedPoints>
42  {
43  using PointT = pcl::PointNormal;
44  };
45  template <> struct PclPointType<PointContentType::eColoredLabeledPoints>
46  {
47  using PointT = pcl::PointXYZRGBL;
48  };
49  template <> struct PclPointType<PointContentType::eColoredOrientedPoints>
50  {
51  using PointT = pcl::PointXYZRGBNormal;
52  };
53 }
54 
55 namespace visionx::tools
56 {
57  /**
58  * @brief Base class for functors with return value.
59  * @param ReturnT The return type.
60  */
61  template <typename ReturnT = void>
63  {
64  using ReturnType = ReturnT;
65  };
66 
67 
68  /**
69  * @brief Call `functor` with the correct pcl point type according to `type`.
70  *
71  * The passed `functor` must have a member functor template, taking the
72  * pcl point type as first template argument:
73  *
74  * @snippet VisionX/libraries/PointCloudTools/test/CallWithPointTypeTest.cpp FunctorDocumentation ExampleFunctor
75  *
76  * Construct your functor and pass it to `callWithPointType()` along with
77  * the respective `PointContentType`:
78  * @snippet VisionX/libraries/PointCloudTools/test/CallWithPointTypeTest.cpp FunctorDocumentation ExampleFunctor_usage
79  *
80  * Depending on the passed `PointContentType`, the functor's `operator()`
81  * is called with the according `pcl::Point...` type as template argument.
82  * This allows you to create `pcl::PointCloud<PointT>` with the correct type.
83  *
84  * In addition to `functor` and `type`, `callWithPointType()` can take
85  * more arguments which will be passed to the functor's `operator()`:
86  *
87  * @snippet VisionX/libraries/PointCloudTools/test/CallWithPointTypeTest.cpp FunctorDocumentation ExampleFunctorTakingArguments
88  * Usage:
89  * @snippet VisionX/libraries/PointCloudTools/test/CallWithPointTypeTest.cpp FunctorDocumentation ExampleFunctorTakingArguments_usage
90  *
91  * If your functor returns a result, have it derive from `FunctorWithReturnType`,
92  * specifying the return type as template argument:
93  *
94  * @snippet VisionX/libraries/PointCloudTools/test/CallWithPointTypeTest.cpp FunctorDocumentation ExampleFunctorReturningInt
95  * Usage:
96  * @snippet VisionX/libraries/PointCloudTools/test/CallWithPointTypeTest.cpp FunctorDocumentation ExampleFunctorReturningInt_usage
97  *
98  * @param functor The functor to be called.
99  * @param type The point content type.
100  * @param args Arguments passed to functor call.
101  */
102  template <class FunctorT, class... Args>
104  callWithPointType(FunctorT& functor, PointContentType type, Args... args)
105  {
106  switch (type)
107  {
108  case PointContentType::ePoints:
109  functor.template operator()<detail::PclPointType<ePoints>::PointT> (args...);
110  break;
111  case PointContentType::eIntensity:
112  functor.template operator()<detail::PclPointType<eIntensity>::PointT>(args...);
113  break;
114  case PointContentType::eColoredPoints:
115  functor.template operator()<detail::PclPointType<eColoredPoints>::PointT>(args...);
116  break;
117  case PointContentType::eLabeledPoints:
118  functor.template operator()<detail::PclPointType<eLabeledPoints>::PointT>(args...);
119  break;
120  case PointContentType::eOrientedPoints:
121  functor.template operator()<detail::PclPointType<eOrientedPoints>::PointT>(args...);
122  break;
123  case PointContentType::eColoredLabeledPoints:
124  functor.template operator()<detail::PclPointType<eColoredLabeledPoints>::PointT>(args...);
125  break;
126  case PointContentType::eColoredOrientedPoints:
127  functor.template operator()<detail::PclPointType<eColoredOrientedPoints>::PointT>(args...);
128  break;
129  }
130  }
131 
132 
133  /// Overload of `visitWithPointType()` for functors passed by const reference.
134  template <class FunctorT, class... Args>
136  callWithPointType(const FunctorT& functor, PointContentType type, Args... args)
137  {
138  switch (type)
139  {
140  case PointContentType::ePoints:
141  functor.template operator()<detail::PclPointType<ePoints>::PointT> (args...);
142  break;
143  case PointContentType::eIntensity:
144  functor.template operator()<detail::PclPointType<eIntensity>::PointT>(args...);
145  break;
146  case PointContentType::eColoredPoints:
147  functor.template operator()<detail::PclPointType<eColoredPoints>::PointT>(args...);
148  break;
149  case PointContentType::eLabeledPoints:
150  functor.template operator()<detail::PclPointType<eLabeledPoints>::PointT>(args...);
151  break;
152  case PointContentType::eOrientedPoints:
153  functor.template operator()<detail::PclPointType<eOrientedPoints>::PointT>(args...);
154  break;
155  case PointContentType::eColoredLabeledPoints:
156  functor.template operator()<detail::PclPointType<eColoredLabeledPoints>::PointT>(args...);
157  break;
158  case PointContentType::eColoredOrientedPoints:
159  functor.template operator()<detail::PclPointType<eColoredOrientedPoints>::PointT>(args...);
160  break;
161  }
162  }
163 
164 
165  /// Overload of `visitWithPointType()` for functors with return value.
166  template <class VisitorT, class... Args>
167  typename VisitorT::ReturnType
168  callWithPointType(VisitorT& functor, PointContentType type, Args... args)
169  {
170  switch (type)
171  {
172  case PointContentType::ePoints:
173  return functor.template operator()<detail::PclPointType<ePoints>::PointT> (args...);
174  break;
175  case PointContentType::eIntensity:
176  return functor.template operator()<detail::PclPointType<eIntensity>::PointT>(args...);
177  break;
178  case PointContentType::eColoredPoints:
179  return functor.template operator()<detail::PclPointType<eColoredPoints>::PointT>(args...);
180  break;
181  case PointContentType::eLabeledPoints:
182  return functor.template operator()<detail::PclPointType<eLabeledPoints>::PointT>(args...);
183  break;
184  case PointContentType::eOrientedPoints:
185  return functor.template operator()<detail::PclPointType<eOrientedPoints>::PointT>(args...);
186  break;
187  case PointContentType::eColoredLabeledPoints:
188  return functor.template operator()<detail::PclPointType<eColoredLabeledPoints>::PointT>(args...);
189  break;
190  case PointContentType::eColoredOrientedPoints:
191  return functor.template operator()<detail::PclPointType<eColoredOrientedPoints>::PointT>(args...);
192  break;
193  }
194  // By throwing an exception, we do not need to provide a return value.
195  ARMARX_UNEXPECTED_ENUM_VALUE(PointContentType, type)
196  }
197 
198 
199  /// Overload of `visitWithPointType()` for functors with return value passed by const reference.
200  template <class VisitorT, class... Args>
201  typename VisitorT::ReturnType
202  callWithPointType(const VisitorT& functor, PointContentType type, Args... args)
203  {
204  switch (type)
205  {
206  case PointContentType::ePoints:
207  return functor.template operator()<detail::PclPointType<ePoints>::PointT> (args...);
208  break;
209  case PointContentType::eIntensity:
210  return functor.template operator()<detail::PclPointType<eIntensity>::PointT>(args...);
211  break;
212  case PointContentType::eColoredPoints:
213  return functor.template operator()<detail::PclPointType<eColoredPoints>::PointT>(args...);
214  break;
215  case PointContentType::eLabeledPoints:
216  return functor.template operator()<detail::PclPointType<eLabeledPoints>::PointT>(args...);
217  break;
218  case PointContentType::eOrientedPoints:
219  return functor.template operator()<detail::PclPointType<eOrientedPoints>::PointT>(args...);
220  break;
221  case PointContentType::eColoredLabeledPoints:
222  return functor.template operator()<detail::PclPointType<eColoredLabeledPoints>::PointT>(args...);
223  break;
224  case PointContentType::eColoredOrientedPoints:
225  return functor.template operator()<detail::PclPointType<eColoredOrientedPoints>::PointT>(args...);
226  break;
227  }
228  // By throwing an exception, we do not need to provide a return value.
229  ARMARX_UNEXPECTED_ENUM_VALUE(PointContentType, type)
230  }
231 
232 
233  /// Functor creating a `pcl::PointCloud<PointT>` and passing it to `function`.
235  {
236  template <class PointT, class FunctionT, class... Args>
237  void operator()(FunctionT& function, Args... args) const
238  {
239  pcl::PointCloud<PointT> pointCloud;
240  function(pointCloud, args...);
241  }
242  template <class PointT, class FunctionT, class... Args>
243  void operator()(const FunctionT& function, Args... args) const
244  {
245  pcl::PointCloud<PointT> pointCloud;
246  function(pointCloud, args...);
247  }
248  };
249 
250  /// Functor creating a `pcl::PointCloud<PointT>::Ptr` and passing it to `function`.
252  {
253  template <class PointT, class FunctionT, class... Args>
254  void operator()(FunctionT& function, Args... args) const
255  {
256  typename pcl::PointCloud<PointT>::Ptr pointCloud(new pcl::PointCloud<PointT>);
257  function(pointCloud, args...);
258  }
259  template <class PointT, class FunctionT, class... Args>
260  void operator()(const FunctionT& function, Args... args) const
261  {
262  typename pcl::PointCloud<PointT>::Ptr pointCloud(new pcl::PointCloud<PointT>);
263  function(pointCloud, args...);
264  }
265  };
266 
267  /**
268  * @brief Call `function` with a `pcl::PointCloud<PointT>` with the
269  * adequate `PointT` according to `type`.
270  *
271  * The passed `function` may be a lambda taking the point cloud by `auto`
272  * as its first argument: `[](auto pointCloud) { pointCloud.size(); } `
273  *
274  * @param function The function to be called.
275  * @param type The point content type.
276  * @param args Optional additional arguments passed to the called function.
277  */
278  template <class FunctionT, class... Args>
279  void callWithPointCloud(FunctionT& function, PointContentType type, Args... args)
280  {
281  callWithPointType(PointCloudFunctor{}, type, function, args...);
282  }
283 
284  /// Overload of `callWithPointCloud()` for functions passed by const reference.
285  template <class FunctionT, class... Args>
286  void callWithPointCloud(const FunctionT& function, PointContentType type, Args... args)
287  {
288  callWithPointType(PointCloudFunctor{}, type, function, args...);
289  }
290 
291  /**
292  * @brief Call `function` with a (non-null) `pcl::PointCloud<PointT>::Ptr`
293  * with the adequate `PointT` according to `type`.
294  *
295  * The passed `function` may be a lambda taking the point cloud by `auto`
296  * as its first argument: `[](auto pointCloud) { pointCloud->size(); } `
297  *
298  * @param function The function to be called.
299  * @param type The point content type.
300  * @param args Optional additional arguments passed to the called function.
301  */
302  template <class FunctionT, class... Args>
303  void callWithPointCloudPtr(FunctionT& function, PointContentType type, Args... args)
304  {
305  callWithPointType(PointCloudPtrFunctor{}, type, function, args...);
306  }
307 
308  /// Overload of `callWithPointCloudPtr()` for functions passed by const reference.
309  template <class FunctionT, class... Args>
310  void callWithPointCloudPtr(const FunctionT& function, PointContentType type, Args... args)
311  {
312  callWithPointType(PointCloudPtrFunctor{}, type, function, args...);
313  }
314 
315 }
ARMARX_UNEXPECTED_ENUM_VALUE
#define ARMARX_UNEXPECTED_ENUM_VALUE(EnumType, value)
Throw an UnexpectedEnumValueException.
Definition: UnexpectedEnumValueException.h:61
visionx::tools
Definition: PCLUtilities.cpp:4
visionx::tools::detail::PclPointType< PointContentType::eIntensity >::PointT
pcl::PointXYZI PointT
Definition: call_with_point_type.h:31
visionx::tools::detail::FunctorWithReturnType
Base class of functors with return value.
Definition: call_with_point_type.h:17
visionx::tools::detail::PclPointType< PointContentType::eColoredPoints >::PointT
pcl::PointXYZRGBA PointT
Definition: call_with_point_type.h:35
visionx::tools::FunctorWithReturnType::ReturnType
ReturnT ReturnType
Definition: call_with_point_type.h:64
visionx::tools::detail::PclPointType< PointContentType::eOrientedPoints >::PointT
pcl::PointNormal PointT
Definition: call_with_point_type.h:43
visionx::tools::PointCloudPtrFunctor
Functor creating a pcl::PointCloud<PointT>::Ptr and passing it to function.
Definition: call_with_point_type.h:251
UnexpectedEnumValueException.h
visionx::tools::PointCloudFunctor::operator()
void operator()(FunctionT &function, Args... args) const
Definition: call_with_point_type.h:237
visionx::tools::callWithPointType
std::enable_if_t< !std::is_base_of< detail::FunctorWithReturnType, FunctorT >::value, void > callWithPointType(FunctorT &functor, PointContentType type, Args... args)
Call functor with the correct pcl point type according to type.
Definition: call_with_point_type.h:104
visionx::tools::detail::PclPointType< PointContentType::eLabeledPoints >::PointT
pcl::PointXYZL PointT
Definition: call_with_point_type.h:39
visionx::tools::FunctorWithReturnType
Base class for functors with return value.
Definition: call_with_point_type.h:62
cxxopts::value
std::shared_ptr< Value > value()
Definition: cxxopts.hpp:926
visionx::tools::callWithPointCloud
void callWithPointCloud(FunctionT &function, PointContentType type, Args... args)
Call function with a pcl::PointCloud<PointT> with the adequate PointT according to type.
Definition: call_with_point_type.h:279
visionx::tools::callWithPointCloudPtr
void callWithPointCloudPtr(FunctionT &function, PointContentType type, Args... args)
Call function with a (non-null) pcl::PointCloud<PointT>::Ptr with the adequate PointT according to ty...
Definition: call_with_point_type.h:303
visionx::tools::detail::PclPointType< PointContentType::ePoints >::PointT
pcl::PointXYZ PointT
Definition: call_with_point_type.h:27
visionx::tools::detail::PclPointType< PointContentType::eColoredOrientedPoints >::PointT
pcl::PointXYZRGBNormal PointT
Definition: call_with_point_type.h:51
visionx::tools::detail::PclPointType
Definition: call_with_point_type.h:21
visionx::tools::detail::PclPointType< PointContentType::eColoredLabeledPoints >::PointT
pcl::PointXYZRGBL PointT
Definition: call_with_point_type.h:47
visionx::tools::PointCloudPtrFunctor::operator()
void operator()(const FunctionT &function, Args... args) const
Definition: call_with_point_type.h:260
visionx::tools::PointCloudPtrFunctor::operator()
void operator()(FunctionT &function, Args... args) const
Definition: call_with_point_type.h:254
visionx::tools::PointCloudFunctor
Functor creating a pcl::PointCloud<PointT> and passing it to function.
Definition: call_with_point_type.h:234
visionx::tools::PointCloudFunctor::operator()
void operator()(const FunctionT &function, Args... args) const
Definition: call_with_point_type.h:243
visionx::PointT
pcl::PointXYZRGBA PointT
Definition: MaskRCNNPointCloudObjectLocalizer.h:79
visionx::tools::detail
Definition: PCLUtilities.h:86
visionx::tools::detail::PclPointType::PointT
pcl::PointXYZ PointT
Definition: call_with_point_type.h:23