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>
70 struct SmartRangeT
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 //=============================================================================
OpenMesh::SmartRangeT::to_vector
auto to_vector(Functor &&f={}) -> std::vector< typename std::decay< decltype(f(std::declval< HandleT >()))>::type >
Convert range to vector.
Definition: SmartRange.hh:184
OpenMesh::SmartRangeT::any_of
auto any_of(Functor &&f) -> bool
Check if any element fulfils condition.
Definition: SmartRange.hh:128
OpenMesh::SmartRangeT
Base class for all smart range types.
Definition: SmartRange.hh:70
OpenMesh::SmartRangeT::min
auto min(Functor &&f) -> typename std::decay< decltype(f(std::declval< HandleT >()))>::type
Compute minimum.
Definition: SmartRange.hh:235
OpenMesh::SmartRangeT::first
auto first(Functor &&f={}) -> HandleT
Get the first element that fulfills a condition.
Definition: SmartRange.hh:219
OpenMesh::SmartRangeT::max
auto max(Functor &&f) -> typename std::decay< decltype(f(std::declval< HandleT >()))>::type
Compute maximum.
Definition: SmartRange.hh:260
OpenMesh::SmartRangeT::minmax
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
OpenMesh
Definition: MeshItems.hh:59
OpenMesh::SmartRangeT::sum
auto sum(Functor &&f) -> typename std::decay< decltype(f(std::declval< HandleT >()))>::type
Computes the sum of elements.
Definition: SmartRange.hh:81
OpenMesh::SmartRangeT::to_array
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
OpenMesh::SmartRangeT::to_set
auto to_set(Functor &&f={}) -> std::set< typename std::decay< decltype(f(std::declval< HandleT >()))>::type >
Convert range to set.
Definition: SmartRange.hh:201
OpenMesh::SmartRangeT::all_of
auto all_of(Functor &&f) -> bool
Check if all elements fulfil condition.
Definition: SmartRange.hh:145
OpenMesh::SmartRangeT::avg
auto avg(Functor &&f) -> typename std::decay< decltype(f(std::declval< HandleT >()))>::type
Computes the average of elements.
Definition: SmartRange.hh:102