DGtal  1.2.0
exampleFunctorHolder.cpp
Go to the documentation of this file.
1 
32 // Inclusions
33 #include <iostream>
34 #include <numeric>
35 #include <iterator>
36 #include <utility>
37 
38 #include "DGtal/base/FunctorHolder.h"
39 #include "DGtal/kernel/PointVector.h"
40 
41 #include "DGtal/base/Common.h"
42 #include "DGtal/helpers/StdDefs.h"
43 #include "ConfigExamples.h"
44 #include "DGtal/io/readers/PGMReader.h"
45 #include "DGtal/io/readers/GenericReader.h"
46 #include "DGtal/images/ImageContainerBySTLVector.h"
47 #include "DGtal/kernel/BasicPointPredicates.h"
48 
50 
53 {
54  return pt.norm() - 1.;
55 }
57 
59 template <typename Point>
60 inline
61 typename Point::Component
63 {
64  return pt.norm() - typename Point::Component(1);
65 }
67 
69 template <typename Point>
70 struct SignedDistToCircle
71 {
72  using Real = typename Point::Component;
73 
74  Point center;
75  Real radius;
76 
77  SignedDistToCircle(Point const& pt, Real r)
78  : center(pt), radius(r)
79  {}
80 
81  inline
82  Real operator() (Point const& pt) const
83  {
84  return (pt - center).norm() - radius;
85  }
86 };
88 
90 template <typename T>
91 struct Binarizer
92 {
93  T threshold;
94  explicit Binarizer(T v) : threshold(v) {}
95  Binarizer& operator= (Binarizer const&) = delete; // This is not a model of boost::Assignable
96  bool operator() (T v) const { return v <= threshold; }
97 };
98 
99 template <typename T>
100 inline
101 decltype(DGtal::functors::holdFunctor(Binarizer<T>(128))) // Deduced return type
103 {
104  return DGtal::functors::holdFunctor( Binarizer<T>(128) );
105 }
107 
109 template <typename Iterator>
110 auto get_mean_binarizer_from_range(Iterator first, Iterator last) // auto as return type
111  -> decltype(DGtal::functors::holdFunctor(Binarizer<decltype(*first / std::distance(first, last))>(0)))
112  // with trailing return type specification using ->
113 {
114  using value_type = typename std::iterator_traits<Iterator>::value_type;
115  auto const mean = std::accumulate(first, last, value_type(0));
116  auto const size = std::distance(first, last);
117  return DGtal::functors::holdFunctor(Binarizer<decltype(mean / size)>(mean / size));
118 }
120 
122 template <typename Image>
123 auto get_mean_binarizer_from_an_image(std::string const& file_name)
124  -> decltype(get_mean_binarizer_from_range(
125  std::declval<Image>().begin(), std::declval<Image>().end() ))
126 {
127  Image const image = DGtal::GenericReader<Image>::import(file_name);
128  return get_mean_binarizer_from_range(image.begin(), image.end());
129 }
131 
132 #if __cplusplus >= 201402L
134 template <typename Iterator>
135 auto get_mean_binarizer_from_range_cpp14(Iterator first, Iterator last)
136 {
137  using value_type = typename std::iterator_traits<Iterator>::value_type;
138  auto const mean = std::accumulate(first, last, value_type(0));
139  auto const size = std::distance(first, last);
140  return DGtal::functors::holdFunctor(Binarizer<decltype(mean / size)>(mean / size));
141 }
143 #endif
144 
146 template <typename T>
147 inline
148 Binarizer<T> makeBinarizer( T const& v ) // T auto-deduced from the parameter v
149 {
150  return Binarizer<T>(v);
151 }
153 
154 #if 0
156 template <
157  typename PointFunctor,
158  typename Predicate
159 >
164 {
166 }
168 #endif
169 
171 template <
172  typename PointFunctor,
173  typename Predicate
174 >
176 makePointFunctorPredicate_Example( PointFunctor const& aFun, Predicate const& aPred )
177 {
179 }
181 
183 template <
184  typename PointFunctor,
185  typename Predicate
186 >
188  typename std::decay<PointFunctor>::type,
189  typename std::decay<Predicate>::type
190 >
191 makePointFunctorPredicate_Example2( PointFunctor && aFun, Predicate && aPred )
192 {
194  typename std::decay<PointFunctor>::type,
195  typename std::decay<Predicate>::type
196  >(
197  std::forward<PointFunctor>(aFun),
198  std::forward<Predicate>(aPred)
199  );
200 }
202 
204 int main()
205 {
206 
208  // Holding a function
209 
210  {
211  std::cout << "Holding a function" << std::endl;
215  std::cout << fn( Point(1, 1) ) << std::endl;
217  }
218 
219  {
220  std::cout << "Holding a templated function" << std::endl;
223  auto fn = DGtal::functors::holdFunctor( templated_signed_dist_to_unit_circle<Point> );
224  std::cout << fn( Point(1, 1) ) << std::endl;
226  }
227 
228  {
229  std::cout << "Holding a function through a lambda" << std::endl;
232  auto fn = DGtal::functors::holdFunctor( [] (Point const& pt) { return signed_dist_to_unit_circle(pt); } );
233  std::cout << fn( Point(1, 1) ) << std::endl;
235  }
236 
237  {
238  std::cout << "Holding a templated function through a lambda" << std::endl;
241  auto fn = DGtal::functors::holdFunctor( [] (Point const& pt) { return templated_signed_dist_to_unit_circle(pt); } );
242  std::cout << fn( Point(1, 1) ) << std::endl;
244  }
245 
246 #if __cplusplus >= 201402L
247  {
248  std::cout << "Holding a templated function through a C++14 lambda" << std::endl;
250  auto fn = DGtal::functors::holdFunctor( [] (auto const& pt) { return templated_signed_dist_to_unit_circle(pt); } );
252  std::cout << fn( Point(1, 1) ) << std::endl; // <- template parameter is resolved to Point
254  }
255 #endif
256 
258  // Holding a functor
259 
260  {
261  std::cout << "Holding a functor by (lvalue) reference" << std::endl;
264  SignedDistToCircle<Point> dist(Point(0, 1), 2);
265  auto fn = DGtal::functors::holdFunctor( dist );
266  std::cout << fn( Point(1, 1) ) << std::endl;
268  }
269 
270  {
271  std::cout << "Holding a functor by rvalue reference" << std::endl;
274  auto fn = DGtal::functors::holdFunctor( SignedDistToCircle<Point>( Point(0, 1), 2 ) );
275  std::cout << fn( Point(1, 1) ) << std::endl;
277  }
278 
279  {
280  std::cout << "Holding a functor by moving it" << std::endl;
283  SignedDistToCircle<Point> dist(Point(0, 1), 2);
284  auto fn = DGtal::functors::holdFunctor( std::move(dist) );
285  std::cout << fn( Point(1, 1) ) << std::endl;
287  }
288 
290  // Holding a lambda
291 
292  {
293  std::cout << "Holding a lambda" << std::endl;
296  Point center(0, 1);
297  double radius = 2;
298 
300  [&center, &radius] (Point const& pt) {
301  return (pt - center).norm() - radius;
302  }
303  );
304  std::cout << fn( Point(1, 1) ) << std::endl;
306  }
307 
308  {
309  std::cout << "Holding a non-unary lambda" << std::endl;
312 
313  auto dist = [] (Point const& pt, Point const& center, double radius)
314  {
315  return (pt - center).norm() - radius;
316  };
317 
318  auto fn = DGtal::functors::holdFunctor( dist );
319 
320  std::cout << fn( Point(1, 1), Point(0, 1), 2 ) << std::endl;
322  }
323 
325  // Copying
326 
327  {
328  std::cout << "Copying a functor held by lvalue reference" << std::endl;
331  SignedDistToCircle<Point> dist(Point(0, 1), 2);
332  auto fn = DGtal::functors::holdFunctor( dist );
333  auto fn2 = fn;
334 
335  std::cout << fn( Point(1, 1) ) << std::endl; // Output: -1
336  std::cout << fn2( Point(1, 1) ) << std::endl; // Output: -1
337 
338  dist.radius = 3; // fn and fn2 both refer to the same functor dist.
339 
340  std::cout << fn( Point(1, 1) ) << std::endl; // Output: -2
341  std::cout << fn2( Point(1, 1) ) << std::endl; // Output: -2
343  }
344 
345  {
346  std::cout << "Copying a lambda held by rvalue reference" << std::endl;
348  int init_cnt = 0;
349  auto fn = DGtal::functors::holdFunctor( [init_cnt] () mutable { return ++init_cnt; } );
350  std::cout << fn() << std::endl; // Output: 1
351  auto fn2 = fn;
352  std::cout << fn2() << std::endl; // Output: 2
353  std::cout << fn() << std::endl; // Output: 3
355  }
356 
358  // Type of FunctorHolder
359 
360  {
361  std::cout << "Storing a FunctorHolder" << std::endl;
362 
365  auto fn = DGtal::functors::holdFunctor( SignedDistToCircle<Point>( Point(0, 1), 2 ) );
367  }
368 
369  {
370  std::cout << "Passing a FunctorHolder" << std::endl;
371 
372  //image import
374  using Point = Image::Point;
375  std::string filename = examplesPath + "samples/contourS.pgm";
376  Image image = DGtal::PGMReader<Image>::importPGM(filename);
377 
379  auto binarizer = DGtal::functors::holdFunctor( [] (Image::Value v) { return v <= 135; } );
380  DGtal::functors::PointFunctorPredicate<Image, decltype(binarizer)> predicate(image, binarizer);
382 
383  Point const pt(50, 25);
384  std::cout << "binarizer(" << image( pt ) << ") = " << predicate( pt ) << std::endl;
385  }
386 
387  {
388  std::cout << "Returning a functor" << std::endl;
390  auto binarizer = get_trivial_binarizer<int>();
392  std::cout << "binarizer(120) = " << binarizer(120) << std::endl;
393  }
394 
395  {
396  std::cout << "Returning a functor using trailing return syntax" << std::endl;
397 
398  //image import
400  using Point = Image::Point;
401  std::string filename = examplesPath + "samples/contourS.pgm";
402  Image image = DGtal::PGMReader<Image>::importPGM(filename);
403 
405  auto binarizer = get_mean_binarizer_from_range(image.begin(), image.end());
406  DGtal::functors::PointFunctorPredicate<Image, decltype(binarizer)> predicate(image, binarizer);
408 
409  Point const pt(50, 25);
410  std::cout << "binarizer(" << image( pt ) << ") = " << predicate( pt ) << std::endl;
411  }
412 
413  {
414  std::cout << "Returning a functor using trailing return syntax and declval" << std::endl;
415 
416  //image import
418  std::string filename = examplesPath + "samples/contourS.pgm";
419 
420  auto binarizer = get_mean_binarizer_from_an_image<Image>(filename);
421 
422  std::cout << "binarizer(120) = " << binarizer(120) << std::endl;
423  }
424 
425  #if __cplusplus >= 201402L
426  {
427  std::cout << "Returning a functor using auto in C++14" << std::endl;
428 
429  //image import
431  using Point = Image::Point;
432  std::string filename = examplesPath + "samples/contourS.pgm";
433  Image image = DGtal::PGMReader<Image>::importPGM(filename);
434 
435  auto binarizer = get_mean_binarizer_from_range_cpp14(image.begin(), image.end());
436  DGtal::functors::PointFunctorPredicate<Image, decltype(binarizer)> predicate(image, binarizer);
437 
438  Point const pt(50, 25);
439  std::cout << "binarizer(" << image( pt ) << ") = " << predicate( pt ) << std::endl;
440  }
441  #endif
442 
443  {
444  std::cout << "Usage of Binarizer factory" << std::endl;
445 
446  //image import
448  using Point = Image::Point;
449  std::string filename = examplesPath + "samples/contourS.pgm";
450  Image image = DGtal::PGMReader<Image>::importPGM(filename);
451 
453  auto binarizer = DGtal::functors::holdFunctor( makeBinarizer(135) );
454  DGtal::functors::PointFunctorPredicate<Image, decltype(binarizer)> predicate(image, binarizer);
456 
457  Point const pt(50, 25);
458  std::cout << "binarizer(" << image( pt ) << ") = " << predicate( pt ) << std::endl;
459  }
460 
461 
462  #if __cplusplus >= 201703L
463  {
464  std::cout << "Binarizer factory using deduction guides of C++17" << std::endl;
465 
466  //image import
468  using Point = Image::Point;
469  std::string filename = examplesPath + "samples/contourS.pgm";
470  Image image = DGtal::PGMReader<Image>::importPGM(filename);
471 
473  auto binarizer = DGtal::functors::holdFunctor( Binarizer(135) ); // Binarizer template parameter is not specified.
474  DGtal::functors::PointFunctorPredicate<Image, decltype(binarizer)> predicate(image, binarizer);
476 
477  Point const pt(50, 25);
478  std::cout << "binarizer(" << image( pt ) << ") = " << predicate( pt ) << std::endl;
479  }
480  #endif
481 
482  {
483  std::cout << "Usage of PointFunctorPredicate factory" << std::endl;
484 
485  //image import
487  using Point = Image::Point;
488  std::string filename = examplesPath + "samples/contourS.pgm";
489  Image image = DGtal::PGMReader<Image>::importPGM(filename);
490 
492  auto binarizer = DGtal::functors::holdFunctor( makeBinarizer(135) );
493  auto predicate = makePointFunctorPredicate_Example( image, binarizer );
495 
496  Point const pt(50, 25);
497  std::cout << "binarizer(" << image( pt ) << ") = " << predicate( pt ) << std::endl;
498  }
499 
500  {
501  std::cout << "Usage of PointFunctorPredicate factory with perfect forwarding" << std::endl;
502 
503  //image import
505  using Point = Image::Point;
506  std::string filename = examplesPath + "samples/contourS.pgm";
507  Image image = DGtal::PGMReader<Image>::importPGM(filename);
508 
509  auto binarizer = DGtal::functors::holdFunctor( makeBinarizer(135) );
510  auto predicate = makePointFunctorPredicate_Example2( image, binarizer );
511 
512  Point const pt(50, 25);
513  std::cout << "binarizer(" << image( pt ) << ") = " << predicate( pt ) << std::endl;
514  }
515  return 0;
516 }
Aim: This class encapsulates its parameter class so that to indicate to the user that the object/poin...
Definition: ConstAlias.h:187
double norm(const NormType type=L_2) const
auto get_mean_binarizer_from_an_image(std::string const &file_name) -> decltype(get_mean_binarizer_from_range(std::declval< Image >().begin(), std::declval< Image >().end()))
[Returning a FunctorHolder using trailing return]
decltype(DGtal::functors::holdFunctor(Binarizer< T >(128))) get_trivial_binarizer()
double signed_dist_to_unit_circle(DGtal::PointVector< 2, double > const &pt)
[signed_dist_to_unit_circle]
DGtal::functors::PointFunctorPredicate< typename std::decay< PointFunctor >::type, typename std::decay< Predicate >::type > makePointFunctorPredicate_Example2(PointFunctor &&aFun, Predicate &&aPred)
[Factory of PointFunctorPredicate]
Point::Component templated_signed_dist_to_unit_circle(Point const &pt)
[signed_dist_to_unit_circle]
auto get_mean_binarizer_from_range(Iterator first, Iterator last) -> decltype(DGtal::functors::holdFunctor(Binarizer< decltype(*first/std::distance(first, last))>(0)))
[Returning a FunctorHolder]
Binarizer< T > makeBinarizer(T const &v)
[Returning a FunctorHolder using trailing return and declval]
DGtal::functors::PointFunctorPredicate< PointFunctor, Predicate > makePointFunctorPredicate_Example(PointFunctor const &aFun, Predicate const &aPred)
[Factory of Binarizer]
int main()
[Factory of PointFunctorPredicate using perfect forwarding]
Point center(const std::vector< Point > &points)
auto holdFunctor(Function &&fn) -> decltype(holdFunctorImpl(std::forward< Function >(fn), typename std::is_lvalue_reference< Function >{}))
Hold any callable object (function, functor, lambda, ...) as a C(Unary)Functor model.
static TContainer import(const std::string &filename, std::vector< unsigned int > dimSpace=std::vector< unsigned int >())
static ImageContainer importPGM(const std::string &aFilename, const Functor &aFunctor=Functor(), bool topbotomOrder=true)
Aim: The predicate returns true when the predicate returns true for the value assigned to a given poi...
MyPointD Point
Definition: testClone2.cpp:383
Image image(domain)
ImageContainerBySTLVector< Domain, Value > Image