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
14{
15 /// Base class of functors with return value.
17 {
18 };
19
20 template <PointContentType pointContentType>
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
69namespace 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>
116 typename std::enable_if_t<!std::is_base_of<detail::FunctorWithReturnType, FunctorT>::value,
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>
150 typename std::enable_if_t<!std::is_base_of<detail::FunctorWithReturnType, FunctorT>::value,
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
#define ARMARX_UNEXPECTED_ENUM_VALUE(EnumType, value)
Throw an UnexpectedEnumValueException.
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...
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.
void callWithPointCloud(FunctionT &function, PointContentType type, Args... args)
Call function with a pcl::PointCloud<PointT> with the adequate PointT according to type.
Base class for functors with return value.
Functor creating a pcl::PointCloud<PointT> and passing it to function.
void operator()(FunctionT &function, Args... args) const
void operator()(const FunctionT &function, Args... args) const
Functor creating a pcl::PointCloud<PointT>::Ptr and passing it to function.
void operator()(FunctionT &function, Args... args) const
void operator()(const FunctionT &function, Args... args) const
Base class of functors with return value.