OpenMesh
SmartRange.hh
1 /* ========================================================================= *
2  * *
3  * OpenMesh *
4  * Copyright (c) 2001-2019, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openmesh.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenMesh. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39  * *
40  * ========================================================================= */
41 
42 
43 #pragma once
44 
45 #include <utility>
46 #include <array>
47 #include <vector>
48 #include <set>
49 
50 //== NAMESPACES ===============================================================
51 
52 namespace OpenMesh {
53 
54 //== FORWARD DECLARATION ======================================================
55 
56 //== CLASS DEFINITION =========================================================
57 
58 namespace {
59 
60 struct Identity
61 {
62  template <typename T>
63  T operator()(const T& _t) const { return _t; }
64 };
65 
66 }
67 
68 template <typename RangeT, typename HandleT, typename Functor>
70 
72 template <typename RangeT, typename HandleT>
74 {
75  using Handle = HandleT;
77  using Range = RangeT;
78 
79  // TODO: Someone with better c++ knowledge may improve the code below.
80 
87  template <typename Functor>
88  auto sum(Functor&& f) -> typename std::decay<decltype (f(std::declval<HandleT>()))>::type
89  {
90  auto range = static_cast<const RangeT*>(this);
91  auto begin = range->begin();
92  auto end = range->end();
93  assert(begin != end);
94  typename std::decay<decltype (f(*begin))>::type result = f(*begin);
95  auto it = begin;
96  ++it;
97  for (; it != end; ++it)
98  result += f(*it);
99  return result;
100  }
101 
108  template <typename Functor>
109  auto avg(Functor&& f) -> typename std::decay<decltype (f(std::declval<HandleT>()))>::type
110  {
111  auto range = static_cast<const RangeT*>(this);
112  auto begin = range->begin();
113  auto end = range->end();
114  assert(begin != end);
115  typename std::decay<decltype (f(*begin))>::type result = f(*begin);
116  auto it = begin;
117  ++it;
118  int n_elements = 1;
119  for (; it != end; ++it)
120  {
121  result += f(*it);
122  ++n_elements;
123  }
124  return (1.0 / n_elements) * result;
125  }
126 
134  template <typename Functor>
135  auto any_of(Functor&& f) -> bool
136  {
137  auto range = static_cast<const RangeT*>(this);
138  for (auto e : *range)
139  if (f(e))
140  return true;
141  return false;
142  }
143 
151  template <typename Functor>
152  auto all_of(Functor&& f) -> bool
153  {
154  auto range = static_cast<const RangeT*>(this);
155  for (auto e : *range)
156  if (!f(e))
157  return false;
158  return true;
159  }
160 
170  template <int n, typename Functor = Identity>
171  auto to_array(Functor&& f = {}) -> std::array<typename std::decay<decltype (f(std::declval<HandleT>()))>::type, n>
172  {
173  auto range = static_cast<const RangeT*>(this);
174  std::array<typename std::decay<decltype (f(std::declval<HandleT>()))>::type, n> res;
175  auto it = range->begin();
176  auto end = range->end();
177  int i = 0;
178  while (i < n && it != end)
179  res[i++] = f(*(it++));
180  return res;
181  }
182 
190  template <typename Functor = Identity>
191  auto to_vector(Functor&& f = {}) -> std::vector<typename std::decay<decltype (f(std::declval<HandleT>()))>::type>
192  {
193  auto range = static_cast<const RangeT*>(this);
194  std::vector<typename std::decay<decltype (f(std::declval<HandleT>()))>::type> res;
195  for (const auto& e : *range)
196  res.push_back(f(e));
197  return res;
198  }
199 
207  template <typename Functor = Identity>
208  auto to_set(Functor&& f = {}) -> std::set<typename std::decay<decltype (f(std::declval<HandleT>()))>::type>
209  {
210  auto range = static_cast<const RangeT*>(this);
211  std::set<typename std::decay<decltype (f(std::declval<HandleT>()))>::type> res;
212  for (const auto& e : *range)
213  res.insert(f(e));
214  return res;
215  }
216 
225  template <typename Functor>
226  auto first(Functor&& f = {}) -> HandleT
227  {
228  auto range = static_cast<const RangeT*>(this);
229  for (const auto& e : *range)
230  if (f(e))
231  return e;
232  return HandleT();
233  }
234 
241  template <typename Functor>
242  auto min(Functor&& f) -> typename std::decay<decltype (f(std::declval<HandleT>()))>::type
243  {
244  using std::min;
245 
246  auto range = static_cast<const RangeT*>(this);
247  auto it = range->begin();
248  auto end = range->end();
249  assert(it != end);
250 
251  typename std::decay<decltype (f(std::declval<HandleT>()))>::type res = f(*it);
252  ++it;
253 
254  for (; it != end; ++it)
255  res = min(res, f(*it));
256 
257  return res;
258  }
259 
266  template <typename Functor>
267  auto argmin(Functor&& f) -> HandleT
268  {
269  auto range = static_cast<const RangeT*>(this);
270  auto it = range->begin();
271  auto min_it = it;
272  auto end = range->end();
273  assert(it != end);
274 
275  typename std::decay<decltype (f(std::declval<HandleT>()))>::type curr_min = f(*it);
276  ++it;
277 
278  for (; it != end; ++it)
279  {
280  auto val = f(*it);
281  if (val < curr_min)
282  {
283  curr_min = val;
284  min_it = it;
285  }
286  }
287 
288  return *min_it;
289  }
290 
297  template <typename Functor>
298  auto max(Functor&& f) -> typename std::decay<decltype (f(std::declval<HandleT>()))>::type
299  {
300  using std::max;
301 
302  auto range = static_cast<const RangeT*>(this);
303  auto it = range->begin();
304  auto end = range->end();
305  assert(it != end);
306 
307  typename std::decay<decltype (f(std::declval<HandleT>()))>::type res = f(*it);
308  ++it;
309 
310  for (; it != end; ++it)
311  res = max(res, f(*it));
312 
313  return res;
314  }
315 
316 
323  template <typename Functor>
324  auto argmax(Functor&& f) -> HandleT
325  {
326  auto range = static_cast<const RangeT*>(this);
327  auto it = range->begin();
328  auto max_it = it;
329  auto end = range->end();
330  assert(it != end);
331 
332  typename std::decay<decltype (f(std::declval<HandleT>()))>::type curr_max = f(*it);
333  ++it;
334 
335  for (; it != end; ++it)
336  {
337  auto val = f(*it);
338  if (val > curr_max)
339  {
340  curr_max = val;
341  max_it = it;
342  }
343  }
344 
345  return *max_it;
346  }
347 
355  template <typename Functor>
356  auto minmax(Functor&& f) -> std::pair<typename std::decay<decltype (f(std::declval<HandleT>()))>::type,
357  typename std::decay<decltype (f(std::declval<HandleT>()))>::type>
358  {
359  return std::make_pair(this->min(f), this->max(f));
360  }
361 
362 
369  template <typename Functor>
370  auto count_if(Functor&& f) -> int
371  {
372  int count = 0;
373  auto range = static_cast<const RangeT*>(this);
374  for (const auto& e : *range)
375  if (f(e))
376  ++count;
377  return count;
378  }
379 
380 
387  template <typename Functor>
388  auto for_each(Functor&& f) -> void
389  {
390  auto range = static_cast<const RangeT*>(this);
391  for (const auto& e : *range)
392  f(e);
393  }
394 
395 
402  template <typename Functor>
404  {
405  auto range = static_cast<const RangeT*>(this);
406  auto b = (*range).begin();
407  auto e = (*range).end();
409  }
410 
411 };
412 
413 
415 template <typename RangeT, typename HandleT, typename Functor>
416 struct FilteredSmartRangeT : public SmartRangeT<FilteredSmartRangeT<RangeT, HandleT, Functor>, HandleT>
417 {
419  using BaseIterator = decltype((std::declval<typename RangeT::Range>().begin()));
420 
421  struct FilteredIterator : public BaseIterator
422  {
423 
424  FilteredIterator(Functor f, BaseIterator it, BaseIterator end): BaseIterator(it), f_(f), end_(end)
425  {
426  if (!f_(*(*this))) // if start is not valid go to first valid one
427  operator++();
428  }
429 
430  FilteredIterator& operator++()
431  {
432  if (BaseIterator::operator==(end_)) // don't go past end
433  return *this;
434 
435  // go to next valid one
436  do
437  BaseIterator::operator++();
438  while (BaseIterator::operator!=(end_) && !f_(*(*this)));
439  return *this;
440  }
441 
442  Functor f_;
443  BaseIterator end_;
444  };
445 
446  FilteredSmartRangeT(Functor f, BaseIterator begin, BaseIterator end) : f_(f), begin_(begin), end_(end){}
447  FilteredIterator begin() const { return FilteredIterator(f_, begin_, end_); }
448  FilteredIterator end() const { return FilteredIterator(f_, end_, end_); }
449 
450  Functor f_;
451  BaseIterator begin_;
452  BaseIterator end_;
453 };
454 
455 
456 
457 //=============================================================================
458 } // namespace OpenMesh
459 //=============================================================================
460 
461 //=============================================================================
auto any_of(Functor &&f) -> bool
Check if any element fulfils condition.
Definition: SmartRange.hh:135
auto to_vector(Functor &&f={}) -> std::vector< typename std::decay< decltype(f(std::declval< HandleT >()))>::type >
Convert range to vector.
Definition: SmartRange.hh:191
auto to_set(Functor &&f={}) -> std::set< typename std::decay< decltype(f(std::declval< HandleT >()))>::type >
Convert range to set.
Definition: SmartRange.hh:208
auto min(Functor &&f) -> typename std::decay< decltype(f(std::declval< HandleT >()))>::type
Compute minimum.
Definition: SmartRange.hh:242
auto filtered(Functor &&f) -> FilteredSmartRangeT< SmartRange, Handle, typename std::decay< Functor >::type >
Only iterate over a subset of elements.
Definition: SmartRange.hh:403
auto for_each(Functor &&f) -> void
Apply a functor to each element.
Definition: SmartRange.hh:388
auto argmin(Functor &&f) -> HandleT
Compute minimal element.
Definition: SmartRange.hh:267
auto sum(Functor &&f) -> typename std::decay< decltype(f(std::declval< HandleT >()))>::type
Computes the sum of elements.
Definition: SmartRange.hh:88
auto minmax(Functor &&f) -> std::pair< typename std::decay< decltype(f(std::declval< HandleT >()))>::type, typename std::decay< decltype(f(std::declval< HandleT >()))>::type >
Computes minimum and maximum.
Definition: SmartRange.hh:356
auto max(Functor &&f) -> typename std::decay< decltype(f(std::declval< HandleT >()))>::type
Compute maximum.
Definition: SmartRange.hh:298
auto first(Functor &&f={}) -> HandleT
Get the first element that fulfills a condition.
Definition: SmartRange.hh:226
auto avg(Functor &&f) -> typename std::decay< decltype(f(std::declval< HandleT >()))>::type
Computes the average of elements.
Definition: SmartRange.hh:109
Base class for all smart range types.
Definition: SmartRange.hh:73
auto count_if(Functor &&f) -> int
Compute number of elements that satisfy a given predicate.
Definition: SmartRange.hh:370
auto to_array(Functor &&f={}) -> std::array< typename std::decay< decltype(f(std::declval< HandleT >()))>::type, n >
Convert range to array.
Definition: SmartRange.hh:171
Contains all the mesh ingredients like the polygonal mesh, the triangle mesh, different mesh kernels ...
Definition: MeshItems.hh:59
Class which applies a filter when iterating over elements.
Definition: SmartRange.hh:69
auto all_of(Functor &&f) -> bool
Check if all elements fulfil condition.
Definition: SmartRange.hh:152
auto argmax(Functor &&f) -> HandleT
Compute maximal element.
Definition: SmartRange.hh:324

Project OpenMesh, ©  Computer Graphics Group, RWTH Aachen. Documentation generated using doxygen .