CTL  0.6.1
Computed Tomography Library
range.h
Go to the documentation of this file.
1 #ifndef CTL_RANGE_H
2 #define CTL_RANGE_H
3 
4 #include <algorithm>
5 #include <cmath>
6 #include <stdexcept>
7 #include <vector>
8 
9 typedef unsigned int uint;
10 
11 namespace CTL {
12 
13 // Range
30 template<typename T>
31 class Range
32 {
33 public:
34  // ctor
41  template<typename T1, typename T2,
42  typename = typename std::enable_if<std::is_convertible<T1, T>::value &&
43  std::is_convertible<T2, T>::value>::type>
44  Range(T1 start, T2 end) : _data{ static_cast<T>(start), static_cast<T>(end) }
45  { }
46 
54  template<typename T1, typename T2,
55  typename = typename std::enable_if<std::is_convertible<T1, T>::value &&
56  std::is_convertible<T2, T>::value>::type>
57  Range(const std::pair<T1, T2>& bounds)
58  : _data{ static_cast<T>(bounds.first), static_cast<T>(bounds.second) }
59  { }
60 
61  static Range fromCenterAndWidth(T center, T width);
62 
63  // start and end of the range
64  T& start();
65  T& end();
66  const T& start() const;
67  const T& end() const;
68 
69  // center of the range
70  T center() const;
71  // width of the range
72  T width() const;
73 
74  // spacing that a linspace vector would have, given a specific number of samples
75  T spacing(uint nbSamples) const;
76 
77  // linspace
78  std::vector<T> linspace(uint nbSamples, bool endpoint = true) const;
79  std::vector<T> expspace(uint nbSamples, bool endpoint = true) const;
80  // static linspace
81  static std::vector<T> linspace(T from, T to, uint nbSamples, bool endpoint = true);
82  static std::vector<T> expspace(T from, T to, uint nbSamples, bool endpoint = true);
83 
84  // conversion (convenience)
85  std::pair<T, T> toPair() const;
86 
87 private:
88  // data member (start and end)
89  T _data[2];
90 };
91 
92 typedef Range<uint> IndexRange;
93 typedef Range<float> SamplingRange;
94 
114 template<typename T>
116 {
117  return Range<T>(center - width / T(2), center + width / T(2));
118 }
119 
125 template<typename T>
126 T Range<T>::width() const { return _data[1] - _data[0]; }
127 
140 template<typename T>
141 T Range<T>::spacing(uint nbSamples) const
142 {
143  return (nbSamples > 1) ? (_data[1] - _data[0]) / T(nbSamples - 1)
144  : T(0);
145 }
146 
150 template<typename T>
151 T& Range<T>::start() { return _data[0]; }
152 
156 template<typename T>
157 T& Range<T>::end() { return _data[1]; }
158 
162 template<typename T>
163 const T& Range<T>::start() const { return _data[0]; }
164 
168 template<typename T>
169 const T& Range<T>::end() const { return _data[1]; }
170 
186 template<typename T>
187 T Range<T>::center() const { return (_data[0] + _data[1]) / T(2); }
188 
202 template<typename T>
203 std::vector<T> Range<T>::linspace(uint nbSamples, bool endpoint) const
204 {
205  return linspace(_data[0], _data[1], nbSamples, endpoint);
206 }
207 
225 template<typename T>
226 std::vector<T> Range<T>::expspace(uint nbSamples, bool endpoint) const
227 {
228  return expspace(_data[0], _data[1], nbSamples, endpoint);
229 }
230 
246 template<typename T>
247 std::vector<T> Range<T>::linspace(T from, T to, uint nbSamples, bool endpoint)
248 {
249  std::vector<T> ret(nbSamples);
250  const T increment = (nbSamples > 1) ? (to - from) / T(nbSamples - endpoint)
251  : T(0);
252  uint idx = 0;
253  std::generate(ret.begin(), ret.end(), [&idx, from, increment]
254  { return from + T(idx++) * increment; });
255 
256  return ret;
257 }
258 
276 template<typename T>
277 std::vector<T> Range<T>::expspace(T from, T to, uint nbSamples, bool endpoint)
278 {
279  if(from <= T(0) || to <= T(0))
280  throw std::domain_error("Range::expspace: Exponential sampling is not supported for "
281  "non-positive sampling points");
282 
283  const auto logVals = Range<double>::linspace(std::log(from), std::log(to), nbSamples, endpoint);
284  std::vector<T> ret(logVals.size());
285 
286  std::transform(logVals.cbegin(), logVals.cend(), ret.begin(), [](double val) {
287  constexpr double roundIfInt = std::is_integral<T>::value ? 0.5 : 0.0;
288  return static_cast<T>(std::exp(val) + roundIfInt);
289  });
290 
291  return ret;
292 }
293 
297 template<typename T>
298 std::pair<T, T> Range<T>::toPair() const
299 {
300  return { _data[0], _data[1] };
301 }
302 
303 } // namespace CTL
304 
306 
326 
328 #endif // CTL_RANGE_H
std::vector< T > linspace(uint nbSamples, bool endpoint=true) const
Generates a vector with nbSamples points that are equally distributed across this range.
Definition: range.h:203
T width() const
Returns the width of the range (i.e. end - start).
Definition: range.h:126
std::vector< T > expspace(uint nbSamples, bool endpoint=true) const
Generates a vector with nbSamples points that are distributed across this range with exponentially in...
Definition: range.h:226
std::pair< T, T > toPair() const
Returns the start and end point of the range as a std::pair.
Definition: range.h:298
T & end()
Returns a (modifiable) reference to the end point of this range.
Definition: range.h:157
T & start()
Returns a (modifiable) reference to the start point of this range.
Definition: range.h:151
Range(const std::pair< T1, T2 > &bounds)
Constructs a Range representing the interval [bounds.first, bounds.second].
Definition: range.h:57
T spacing(uint nbSamples) const
Returns the spacing that two sampling points would have if this range were divided into nbSamples equ...
Definition: range.h:141
unsigned int uint
Qt style alias for unsigned int.
Definition: modulelayout.h:6
Range(T1 start, T2 end)
Constructs a Range representing the interval [start, end].
Definition: range.h:44
T center() const
Returns the center point of this range.
Definition: range.h:187
static Range fromCenterAndWidth(T center, T width)
Creates a Range object describing an interval of width width centered at center.
Definition: range.h:115
The Range class holds start and end point of a value range (or interval) and provides a few convenien...
Definition: sparsevoxelvolume.h:12