| 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>
69 struct FilteredSmartRangeT;
70
72 template <typename RangeT, typename HandleT>
73 struct SmartRangeT
74 {
75 using Handle = HandleT;
76 using SmartRange = SmartRangeT<RangeT, 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>
403 auto filtered(Functor&& f) -> FilteredSmartRangeT<SmartRange, Handle, typename std::decay<Functor>::type>
404 {
405 auto range = static_cast<const RangeT*>(this);
406 auto b = (*range).begin();
407 auto e = (*range).end();
408 return FilteredSmartRangeT<SmartRange, Handle, typename std::decay<Functor>::type>(f, b, e);
409 }
410
411 };
412
413
415 template <typename RangeT, typename HandleT, typename Functor>
416 struct FilteredSmartRangeT : public SmartRangeT<FilteredSmartRangeT<RangeT, HandleT, Functor>, HandleT>
417 {
418 using BaseRange = SmartRangeT<FilteredSmartRangeT<RangeT, HandleT, Functor>, HandleT>;
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 //=============================================================================
OpenMesh::SmartRangeT::any_of
auto any_of(Functor &&f) -> bool
Check if any element fulfils condition.
Definition: SmartRange.hh:135
OpenMesh::FilteredSmartRangeT::FilteredIterator
Definition: SmartRange.hh:421
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:191
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:208
OpenMesh::SmartRangeT::min
auto min(Functor &&f) -> typename std::decay< decltype(f(std::declval< HandleT >()))>::type
Compute minimum.
Definition: SmartRange.hh:242
OpenMesh::SmartRangeT::filtered
auto filtered(Functor &&f) -> FilteredSmartRangeT< SmartRange, Handle, typename std::decay< Functor >::type >
Only iterate over a subset of elements.
Definition: SmartRange.hh:403
OpenMesh::SmartRangeT::for_each
auto for_each(Functor &&f) -> void
Apply a functor to each element.
Definition: SmartRange.hh:388
OpenMesh::SmartRangeT::argmin
auto argmin(Functor &&f) -> HandleT
Compute minimal element.
Definition: SmartRange.hh:267
OpenMesh::SmartRangeT::sum
auto sum(Functor &&f) -> typename std::decay< decltype(f(std::declval< HandleT >()))>::type
Computes the sum of elements.
Definition: SmartRange.hh:88
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:356
OpenMesh::SmartRangeT::max
auto max(Functor &&f) -> typename std::decay< decltype(f(std::declval< HandleT >()))>::type
Compute maximum.
Definition: SmartRange.hh:298
OpenMesh::SmartRangeT::first
auto first(Functor &&f={}) -> HandleT
Get the first element that fulfills a condition.
Definition: SmartRange.hh:226
OpenMesh::SmartRangeT::avg
auto avg(Functor &&f) -> typename std::decay< decltype(f(std::declval< HandleT >()))>::type
Computes the average of elements.
Definition: SmartRange.hh:109
OpenMesh::SmartRangeT
Base class for all smart range types.
Definition: SmartRange.hh:73
OpenMesh::SmartRangeT::count_if
auto count_if(Functor &&f) -> int
Compute number of elements that satisfy a given predicate.
Definition: SmartRange.hh:370
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:171
OpenMesh
Contains all the mesh ingredients like the polygonal mesh, the triangle mesh, different mesh kernels ...
Definition: MeshItems.hh:59
OpenMesh::FilteredSmartRangeT
Class which applies a filter when iterating over elements.
Definition: SmartRange.hh:69
OpenMesh::SmartRangeT::all_of
auto all_of(Functor &&f) -> bool
Check if all elements fulfil condition.
Definition: SmartRange.hh:152
OpenMesh::SmartRangeT::argmax
auto argmax(Functor &&f) -> HandleT
Compute maximal element.
Definition: SmartRange.hh:324