Developer Documentation
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 
69 template <typename RangeT, typename HandleT>
71 {
72  // TODO: Someone with better c++ knowledge may improve the code below.
73 
80  template <typename Functor>
81  auto sum(Functor&& f) -> typename std::decay<decltype (f(std::declval<HandleT>()))>::type
82  {
83  auto range = static_cast<const RangeT*>(this);
84  auto begin = range->begin();
85  auto end = range->end();
86  assert(begin != end);
87  typename std::decay<decltype (f(*begin))>::type result = f(*begin);
88  auto it = begin;
89  ++it;
90  for (; it != end; ++it)
91  result += f(*it);
92  return result;
93  }
94 
101  template <typename Functor>
102  auto avg(Functor&& f) -> typename std::decay<decltype (f(std::declval<HandleT>()))>::type
103  {
104  auto range = static_cast<const RangeT*>(this);
105  auto begin = range->begin();
106  auto end = range->end();
107  assert(begin != end);
108  typename std::decay<decltype (f(*begin))>::type result = f(*begin);
109  auto it = begin;
110  ++it;
111  int n_elements = 1;
112  for (; it != end; ++it)
113  {
114  result += f(*it);
115  ++n_elements;
116  }
117  return (1.0 / n_elements) * result;
118  }
119 
127  template <typename Functor>
128  auto any_of(Functor&& f) -> bool
129  {
130  auto range = static_cast<const RangeT*>(this);
131  for (auto e : *range)
132  if (f(e))
133  return true;
134  return false;
135  }
136 
144  template <typename Functor>
145  auto all_of(Functor&& f) -> bool
146  {
147  auto range = static_cast<const RangeT*>(this);
148  for (auto e : *range)
149  if (!f(e))
150  return false;
151  return true;
152  }
153 
163  template <int n, typename Functor = Identity>
164  auto to_array(Functor&& f = {}) -> std::array<typename std::decay<decltype (f(std::declval<HandleT>()))>::type, n>
165  {
166  auto range = static_cast<const RangeT*>(this);
167  std::array<typename std::decay<decltype (f(std::declval<HandleT>()))>::type, n> res;
168  auto it = range->begin();
169  auto end = range->end();
170  int i = 0;
171  while (i < n && it != end)
172  res[i++] = f(*(it++));
173  return res;
174  }
175 
183  template <typename Functor = Identity>
184  auto to_vector(Functor&& f = {}) -> std::vector<typename std::decay<decltype (f(std::declval<HandleT>()))>::type>
185  {
186  auto range = static_cast<const RangeT*>(this);
187  std::vector<typename std::decay<decltype (f(std::declval<HandleT>()))>::type> res;
188  for (const auto& e : *range)
189  res.push_back(f(e));
190  return res;
191  }
192 
200  template <typename Functor = Identity>
201  auto to_set(Functor&& f = {}) -> std::set<typename std::decay<decltype (f(std::declval<HandleT>()))>::type>
202  {
203  auto range = static_cast<const RangeT*>(this);
204  std::set<typename std::decay<decltype (f(std::declval<HandleT>()))>::type> res;
205  for (const auto& e : *range)
206  res.insert(f(e));
207  return res;
208  }
209 
218  template <typename Functor>
219  auto first(Functor&& f = {}) -> HandleT
220  {
221  auto range = static_cast<const RangeT*>(this);
222  for (const auto& e : *range)
223  if (f(e))
224  return e;
225  return HandleT();
226  }
227 
234  template <typename Functor>
235  auto min(Functor&& f) -> typename std::decay<decltype (f(std::declval<HandleT>()))>::type
236  {
237  using std::min;
238 
239  auto range = static_cast<const RangeT*>(this);
240  auto it = range->begin();
241  auto end = range->end();
242  assert(it != end);
243 
244  typename std::decay<decltype (f(std::declval<HandleT>()))>::type res = f(*it);
245  ++it;
246 
247  for (; it != end; ++it)
248  res = min(res, f(*it));
249 
250  return res;
251  }
252 
259  template <typename Functor>
260  auto max(Functor&& f) -> typename std::decay<decltype (f(std::declval<HandleT>()))>::type
261  {
262  using std::max;
263 
264  auto range = static_cast<const RangeT*>(this);
265  auto it = range->begin();
266  auto end = range->end();
267  assert(it != end);
268 
269  typename std::decay<decltype (f(std::declval<HandleT>()))>::type res = f(*it);
270  ++it;
271 
272  for (; it != end; ++it)
273  res = max(res, f(*it));
274 
275  return res;
276  }
277 
285  template <typename Functor>
286  auto minmax(Functor&& f) -> std::pair<typename std::decay<decltype (f(std::declval<HandleT>()))>::type,
287  typename std::decay<decltype (f(std::declval<HandleT>()))>::type>
288  {
289  return std::make_pair(this->min(f), this->max(f));
290  }
291 
292 
293 
294 
295 
296 };
297 
298 
299 
300 //=============================================================================
301 } // namespace OpenMesh
302 //=============================================================================
303 
304 //=============================================================================
auto to_vector(Functor &&f={}) -> std::vector< typename std::decay< decltype(f(std::declval< HandleT >()))>::type >
Convert range to vector.
Definition: SmartRange.hh:184
auto any_of(Functor &&f) -> bool
Check if any element fulfils condition.
Definition: SmartRange.hh:128
Base class for all smart range types.
Definition: SmartRange.hh:70
auto min(Functor &&f) -> typename std::decay< decltype(f(std::declval< HandleT >()))>::type
Compute minimum.
Definition: SmartRange.hh:235
auto first(Functor &&f={}) -> HandleT
Get the first element that fulfills a condition.
Definition: SmartRange.hh:219
auto max(Functor &&f) -> typename std::decay< decltype(f(std::declval< HandleT >()))>::type
Compute maximum.
Definition: SmartRange.hh:260
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:286
auto sum(Functor &&f) -> typename std::decay< decltype(f(std::declval< HandleT >()))>::type
Computes the sum of elements.
Definition: SmartRange.hh:81
auto to_array(Functor &&f={}) -> std::array< typename std::decay< decltype(f(std::declval< HandleT >()))>::type, n >
Convert range to array.
Definition: SmartRange.hh:164
auto to_set(Functor &&f={}) -> std::set< typename std::decay< decltype(f(std::declval< HandleT >()))>::type >
Convert range to set.
Definition: SmartRange.hh:201
auto all_of(Functor &&f) -> bool
Check if all elements fulfil condition.
Definition: SmartRange.hh:145
auto avg(Functor &&f) -> typename std::decay< decltype(f(std::declval< HandleT >()))>::type
Computes the average of elements.
Definition: SmartRange.hh:102