SmartRange.hh 8.9 KB
Newer Older
Max Lyon's avatar
Max Lyon committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
/* ========================================================================= *
 *                                                                           *
 *                               OpenMesh                                    *
 *           Copyright (c) 2001-2019, RWTH-Aachen University                 *
 *           Department of Computer Graphics and Multimedia                  *
 *                          All rights reserved.                             *
 *                            www.openmesh.org                               *
 *                                                                           *
 *---------------------------------------------------------------------------*
 * This file is part of OpenMesh.                                            *
 *---------------------------------------------------------------------------*
 *                                                                           *
 * Redistribution and use in source and binary forms, with or without        *
 * modification, are permitted provided that the following conditions        *
 * are met:                                                                  *
 *                                                                           *
 * 1. Redistributions of source code must retain the above copyright notice, *
 *    this list of conditions and the following disclaimer.                  *
 *                                                                           *
 * 2. Redistributions in binary form must reproduce the above copyright      *
 *    notice, this list of conditions and the following disclaimer in the    *
 *    documentation and/or other materials provided with the distribution.   *
 *                                                                           *
 * 3. Neither the name of the copyright holder nor the names of its          *
 *    contributors may be used to endorse or promote products derived from   *
 *    this software without specific prior written permission.               *
 *                                                                           *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS       *
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A           *
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  *
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,       *
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR        *
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF    *
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING      *
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS        *
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.              *
 *                                                                           *
 * ========================================================================= */


#pragma once

#include <utility>
Max Lyon's avatar
Max Lyon committed
46
47
#include <array>
#include <vector>
Max Lyon's avatar
Max Lyon committed
48
49
50
51
52
53
54
55
56

//== NAMESPACES ===============================================================

namespace OpenMesh {

//== FORWARD DECLARATION ======================================================

//== CLASS DEFINITION =========================================================

Max Lyon's avatar
Max Lyon committed
57
58
59
60
61
62
63
64
65
66
namespace  {

struct Identity
{
  template <typename T>
  T operator()(const T& _t) const { return _t; }
};

}

Max Lyon's avatar
Max Lyon committed
67
68
69
70
71
72
/// Base class for all smart range types
template <typename RangeT, typename HandleT>
struct SmartRangeT
{
  // TODO: Someone with better c++ knowledge may improve the code below.

Max Lyon's avatar
Max Lyon committed
73
74
75
76
77
78
  /** @brief Computes the sum of elements.
   *
   * Computes the sum of all elements in the range after applying the functor \p f.
   *
   *  @param f Functor that is applied to all elements before computing the sum
   */
Max Lyon's avatar
Max Lyon committed
79
  template <typename Functor>
80
  auto sum(Functor&& f) -> decltype (f(std::declval<HandleT>())+f(std::declval<HandleT>()))
Max Lyon's avatar
Max Lyon committed
81
82
83
84
85
86
87
88
89
90
91
92
93
  {
    auto range = static_cast<const RangeT*>(this);
    auto begin = range->begin();
    auto end   = range->end();
    assert(begin != end);
    decltype (f(*begin) + f(*begin)) sum = f(*begin);
    auto it = begin;
    ++it;
    for (; it != end; ++it)
      sum += f(*it);
    return sum;
  }

Max Lyon's avatar
Max Lyon committed
94
95
96
97
98
99
  /** @brief Computes the average of elements.
   *
   * Computes the average of all elements in the range after applying the functor \p f.
   *
   *  @param f Functor that is applied to all elements before computing the average.
   */
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
  template <typename Functor>
  auto avg(Functor&& f) -> decltype (1.0 * (f(std::declval<HandleT>())+f(std::declval<HandleT>())))
  {
    auto range = static_cast<const RangeT*>(this);
    auto begin = range->begin();
    auto end   = range->end();
    assert(begin != end);
    decltype (f(*begin) + f(*begin)) sum = f(*begin);
    auto it = begin;
    ++it;
    int n_elements = 1;
    for (; it != end; ++it)
    {
      sum += f(*it);
      ++n_elements;
    }
    return (1.0 / n_elements) * sum;
  }

Max Lyon's avatar
Max Lyon committed
119
120
121
122
123
124
125
126
127
  /** @brief Convert range to array.
  *
  * Converts the range of elements into an array of objects returned by functor \p f.
  * The size of the array needs to be provided by the user. If the size is larger than the number of
  * elements in the range, the remaining entries of the array will be uninitialized.
  *
  *  @param f Functor that is applied to all elements before putting them into the array. If no functor is provided
  *           the array will contain the handles.
  */
Max Lyon's avatar
Max Lyon committed
128
129
130
131
132
133
134
135
136
137
138
139
140
  template <int n, typename Functor = Identity>
  auto to_array(Functor&& f = {}) -> std::array<typename std::remove_reference<decltype (f(std::declval<HandleT>()))>::type, n>
  {
    auto range = static_cast<const RangeT*>(this);
    std::array<typename std::remove_reference<decltype (f(std::declval<HandleT>()))>::type, n> res;
    auto it = range->begin();
    auto end = range->end();
    int i = 0;
    while (i < n && it != end)
      res[i++] = f(*(it++));
    return res;
  }

Max Lyon's avatar
Max Lyon committed
141
142
143
144
145
146
147
  /** @brief Convert range to vector.
  *
  * Converts the range of elements into a vector of objects returned by functor \p f.
  *
  *  @param f Functor that is applied to all elements before putting them into the vector. If no functor is provided
  *           the vector will contain the handles.
  */
Max Lyon's avatar
Max Lyon committed
148
149
150
151
152
  template <typename Functor = Identity>
  auto to_vector(Functor&& f = {}) -> std::vector<typename std::remove_reference<decltype (f(std::declval<HandleT>()))>::type>
  {
    auto range = static_cast<const RangeT*>(this);
    std::vector<typename std::remove_reference<decltype (f(std::declval<HandleT>()))>::type> res;
Max Lyon's avatar
Max Lyon committed
153
    for (const auto& e : *range)
Max Lyon's avatar
Max Lyon committed
154
155
156
157
      res.push_back(f(e));
    return res;
  }

Max Lyon's avatar
Max Lyon committed
158
159
160
161
162
163
  /** @brief Compute minimum.
  *
  * Computes the minimum of all objects returned by functor \p f.
  *
  *  @param f Functor that is applied to all elements before computing minimum.
  */
164
165
  template <typename Functor>
  auto min(Functor&& f) -> typename std::remove_reference<decltype (f(std::declval<HandleT>()))>::type
Max Lyon's avatar
Max Lyon committed
166
  {
167
168
    using std::min;

Max Lyon's avatar
Max Lyon committed
169
170
171
172
173
    auto range = static_cast<const RangeT*>(this);
    auto it    = range->begin();
    auto end   = range->end();
    assert(it != end);

174
    typename std::remove_reference<decltype (f(std::declval<HandleT>()))>::type res = f(*it);
Max Lyon's avatar
Max Lyon committed
175
176
177
    ++it;

    for (; it != end; ++it)
178
      res = min(res, f(*it));
Max Lyon's avatar
Max Lyon committed
179

180
    return res;
Max Lyon's avatar
Max Lyon committed
181
182
  }

Max Lyon's avatar
Max Lyon committed
183
184
185
186
187
188
  /** @brief Compute maximum.
  *
  * Computes the maximum of all objects returned by functor \p f.
  *
  *  @param f Functor that is applied to all elements before computing maximum.
  */
189
190
  template <typename Functor>
  auto max(Functor&& f) -> typename std::remove_reference<decltype (f(std::declval<HandleT>()))>::type
Max Lyon's avatar
Max Lyon committed
191
  {
192
193
    using std::max;

Max Lyon's avatar
Max Lyon committed
194
195
196
197
198
    auto range = static_cast<const RangeT*>(this);
    auto it    = range->begin();
    auto end   = range->end();
    assert(it != end);

199
    typename std::remove_reference<decltype (f(std::declval<HandleT>()))>::type res = f(*it);
Max Lyon's avatar
Max Lyon committed
200
201
202
    ++it;

    for (; it != end; ++it)
203
      res = max(res, f(*it));
Max Lyon's avatar
Max Lyon committed
204

205
206
207
    return res;
  }

Max Lyon's avatar
Max Lyon committed
208
209
210
211
212
213
214
  /** @brief Computes minimum and maximum.
  *
  * Computes the minimum and maximum of all objects returned by functor \p f. Result is returned as std::pair
  * containing minimum as first and maximum as second element.
  *
  *  @param f Functor that is applied to all elements before computing maximum.
  */
215
216
217
218
219
  template <typename Functor>
  auto minmax(Functor&& f) -> std::pair<typename std::remove_reference<decltype (f(std::declval<HandleT>()))>::type,
                                        typename std::remove_reference<decltype (f(std::declval<HandleT>()))>::type>
  {
    return std::make_pair(this->min(f), this->max(f));
Max Lyon's avatar
Max Lyon committed
220
221
222
223
  }



224
225


Max Lyon's avatar
Max Lyon committed
226
227
228
229
230
231
232
233
234
};



//=============================================================================
} // namespace OpenMesh
//=============================================================================

//=============================================================================