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