ITK  5.1.0
Insight Toolkit
itkIndexRange.h
Go to the documentation of this file.
1 /*=========================================================================
2  *
3  * Copyright NumFOCUS
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0.txt
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  *=========================================================================*/
18 
19 #ifndef itkIndexRange_h
20 #define itkIndexRange_h
21 
22 #include <cassert>
23 #include <cstddef> // For ptrdiff_t.
24 #include <iterator> // For bidirectional_iterator_tag and reverse_iterator.
25 #include <type_traits> // For conditional and enable_if.
26 
27 #include "itkImageRegion.h"
28 #include "itkIndex.h"
29 #include "itkSize.h"
30 
31 namespace itk
32 {
33 namespace Experimental
34 {
35 
79 template <unsigned VDimension, bool VBeginAtZero>
80 class IndexRange final
81 {
82 public:
83  constexpr static unsigned Dimension = VDimension;
86 
87  class const_iterator final
88  {
89  public:
90  // Types conforming the iterator requirements of the C++ standard library:
91  using difference_type = std::ptrdiff_t;
93  using reference = const IndexType &;
94  using pointer = const IndexType *;
95  using iterator_category = std::bidirectional_iterator_tag;
96 
102  const_iterator() = default;
103 
104 
106  reference operator*() const ITK_NOEXCEPT { return m_Index; }
107 
108 
110  pointer operator->() const ITK_NOEXCEPT { return &(**this); }
111 
112 
115  operator++() ITK_NOEXCEPT
116  {
117  for (unsigned i = 0; i < (VDimension - 1); ++i)
118  {
119  auto & indexValue = m_Index[i];
121 
122  ++indexValue;
123 
124  if (indexValue <= m_MaxIndex[i])
125  {
126  return *this;
127  }
128  indexValue = m_MinIndex[i];
129  }
130  ++m_Index.back();
131 
132  return *this;
133  }
134 
135 
139  operator++(int) ITK_NOEXCEPT
140  {
141  auto result = *this;
142  ++(*this);
143  return result;
144  }
146 
147 
150  operator--() ITK_NOEXCEPT
151  {
152  for (unsigned i = 0; i < (VDimension - 1); ++i)
153  {
154  auto & indexValue = m_Index[i];
156 
157  --indexValue;
158 
159  if (indexValue >= m_MinIndex[i])
160  {
161  return *this;
162  }
163  indexValue = m_MaxIndex[i];
164  }
165  --m_Index.back();
166  return *this;
167  }
168 
169 
173  operator--(int) ITK_NOEXCEPT
174  {
175  auto result = *this;
176  --(*this);
177  return result;
178  }
180 
181 
185  friend bool
186  operator==(const const_iterator & lhs, const const_iterator & rhs) ITK_NOEXCEPT
187  {
188  assert(lhs.m_MaxIndex == rhs.m_MaxIndex);
189 
190  return lhs.m_Index == rhs.m_Index;
191  }
192 
193 
195  friend bool
196  operator!=(const const_iterator & lhs, const const_iterator & rhs) ITK_NOEXCEPT
197  {
198  // Implemented just like the corresponding std::rel_ops operator.
199  return !(lhs == rhs);
200  }
201 
202 
204  friend bool
205  operator<(const const_iterator & lhs, const const_iterator & rhs) ITK_NOEXCEPT
206  {
207  for (unsigned i = VDimension; i > 0; --i)
208  {
209  const auto difference = lhs.m_Index[i - 1] - rhs.m_Index[i - 1];
211 
212  if (difference < 0)
213  {
214  return true;
215  }
216  if (difference > 0)
217  {
218  break;
219  }
220  }
221  return false;
222  }
223 
224 
226  friend bool
227  operator>(const const_iterator & lhs, const const_iterator & rhs) ITK_NOEXCEPT
228  {
229  // Implemented just like the corresponding std::rel_ops operator.
230  return rhs < lhs;
231  }
232 
233 
235  friend bool
236  operator<=(const const_iterator & lhs, const const_iterator & rhs) ITK_NOEXCEPT
237  {
238  // Implemented just like the corresponding std::rel_ops operator.
239  return !(rhs < lhs);
240  }
241 
242 
244  friend bool
245  operator>=(const const_iterator & lhs, const const_iterator & rhs) ITK_NOEXCEPT
246  {
247  // Implemented just like the corresponding std::rel_ops operator.
248  return !(lhs < rhs);
249  }
250 
251 
252  private:
253  friend class IndexRange;
254 
255  // Represents an N-dimensional index that is always zero
256  // Aims towards zero runtime overhead.
257  struct ZeroIndex
258  {
259  // The "index" operator.
260  constexpr IndexValueType operator[](unsigned) const { return 0; }
261 
262  // Implicitly converts to a default-initialized itk::Index<N>.
263  constexpr operator IndexType() const { return IndexType(); }
264  };
265 
266 
267  // When BeginAtZero is true, use zero as minimum index, otherwise use itk::Index<N>.
268  using MinIndexType = typename std::conditional<VBeginAtZero, ZeroIndex, IndexType>::type;
269 
270  // Private constructor, only used by friend class IndexRange.
271  const_iterator(const IndexType & index, const MinIndexType & minIndex, const IndexType & maxIndex) ITK_NOEXCEPT
272  :
273  // Note: Use parentheses instead of curly braces to initialize data members,
274  // to avoid AppleClang 6.0.0.6000056 compilation error, "no viable conversion..."
275  m_Index(index)
276  , m_MinIndex(minIndex)
277  , m_MaxIndex(maxIndex)
278  {}
279 
280 
281  // IndexRange::const_iterator data members:
282 
283  // Current (N-dimensional) index.
285 
286  // Minimum (N-dimensional) index.
288 
289  // Maximum (N-dimensional) index.
291  };
292 
294  using reverse_iterator = std::reverse_iterator<iterator>;
295  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
296 
302  IndexRange() = default;
303 
304 
307  explicit IndexRange(const SizeType & gridSize)
308  : // Note: Use parentheses instead of curly braces to initialize data members,
309  // to avoid AppleClang 6.0.0.6000056 compile errors, "no viable conversion..."
310  m_MinIndex()
311  , m_MaxIndex(CalculateMaxIndex(typename iterator::MinIndexType(), gridSize))
312  {}
313 
314 
319  template <bool VIsSubstitutionFailure = VBeginAtZero,
320  typename TVoid = typename std::enable_if<!VIsSubstitutionFailure>::type>
321  explicit IndexRange(const ImageRegion<VDimension> & imageRegion)
322  : // Note: Use parentheses instead of curly braces to initialize data members,
323  // to avoid AppleClang 6.0.0.6000056 compile errors, "no viable conversion..."
324  m_MinIndex(imageRegion.GetIndex())
325  , m_MaxIndex(CalculateMaxIndex(imageRegion.GetIndex(), imageRegion.GetSize()))
326  {
327  // Three compile-time asserts, just to check if SFINAE worked properly:
328  static_assert(!VIsSubstitutionFailure,
329  "This template should (of course) be instantiated without substitution failure.");
330  static_assert(std::is_same<TVoid, void>::value,
331  "std::enable_if<!VIsSubstitutionFailure> should yield void, by definition.");
332  static_assert(!VBeginAtZero, "This constructor should only be is available when VBeginAtZero is false.");
333  }
335 
336 
338  iterator
339  begin() const ITK_NOEXCEPT
340  {
342  }
343 
345  iterator
346  end() const ITK_NOEXCEPT
347  {
348  IndexType index = m_MinIndex;
349  index.back() = m_MaxIndex.back() + 1;
350  return iterator(index, m_MinIndex, m_MaxIndex);
351  }
353 
356  const_iterator
357  cbegin() const ITK_NOEXCEPT
358  {
359  return this->begin();
360  }
361 
363  const_iterator
364  cend() const ITK_NOEXCEPT
365  {
366  return this->end();
367  }
368 
371  rbegin() const ITK_NOEXCEPT
372  {
373  return reverse_iterator(this->end());
374  }
375 
378  rend() const ITK_NOEXCEPT
379  {
380  return reverse_iterator(this->begin());
381  }
382 
385  crbegin() const ITK_NOEXCEPT
386  {
387  return this->rbegin();
388  }
389 
392  crend() const ITK_NOEXCEPT
393  {
394  return this->rend();
395  }
396 
397 
399  std::size_t
400  size() const ITK_NOEXCEPT
401  {
402  std::size_t result = 1;
403 
404  for (unsigned i = 0; i < VDimension; ++i)
405  {
406  result *= ((m_MaxIndex[i] + 1) - m_MinIndex[i]);
407  }
408  return result;
409  }
410 
411 
413  bool
414  empty() const ITK_NOEXCEPT
415  {
416  // When an IndexRange is empty, each index value of m_MaxIndex is less than the corresponding
417  // index value of m_MinIndex. And vise versa: when an IndexRange is non-empty, each index value
418  // of m_MaxIndex is greater than or equal to the corresponding index value of m_MinIndex.
419  // Note that the range contains one element when m_MaxIndex == m_MinIndex.
420  return m_MaxIndex[0] < m_MinIndex[0];
421  }
422 
423 
424 private:
426 
427  static IndexType
428  CalculateMaxIndex(const MinIndexType & minIndex, const SizeType & size)
429  {
430  const bool sizeHasZeroValue = [&size] {
431  for (const auto sizeValue : size)
432  {
433  if (sizeValue == 0)
434  {
435  return true;
436  }
437  }
438  return false;
439  }();
440 
441  // Treat any size that has a zero value equally.
442  const SizeType normalizedSize = sizeHasZeroValue ? SizeType{ { 0 } } : size;
443 
444  IndexType index;
445 
446  for (unsigned i = 0; i < VDimension; ++i)
447  {
448  index[i] = minIndex[i] + static_cast<IndexValueType>(normalizedSize[i]) - 1;
449  }
450 
451  return index;
452  }
453 
454  // IndexRange data members:
455 
456  // Minimum (N-dimensional) index.
458 
459  // Maximum (N-dimensional) index.
461 };
462 
463 template <unsigned VDimension>
465 
466 template <unsigned VDimension>
468 
469 } // namespace Experimental
470 } // namespace itk
471 
472 #endif
itk::Experimental::IndexRange::const_iterator::operator++
const_iterator & operator++() noexcept
Definition: itkIndexRange.h:115
itk::Experimental::IndexRange::const_iterator::m_MinIndex
MinIndexType m_MinIndex
Definition: itkIndexRange.h:287
itk::Experimental::IndexRange::crbegin
const_reverse_iterator crbegin() const noexcept
Definition: itkIndexRange.h:385
itk::Experimental::IndexRange::const_iterator::m_Index
IndexType m_Index
Definition: itkIndexRange.h:284
itk::Experimental::IndexRange::const_iterator::operator--
const_iterator operator--(int) noexcept
Definition: itkIndexRange.h:173
itk::Experimental::IndexRange::reverse_iterator
std::reverse_iterator< iterator > reverse_iterator
Definition: itkIndexRange.h:294
itk::Experimental::IndexRange::end
iterator end() const noexcept
Definition: itkIndexRange.h:346
itk::Experimental::IndexRange::size
std::vcl_size_t size() const noexcept
Definition: itkIndexRange.h:400
itk::Index
Represent a n-dimensional index in a n-dimensional image.
Definition: itkIndex.h:66
itk::Experimental::IndexRange::IndexRange
IndexRange(const ImageRegion< VDimension > &imageRegion)
Definition: itkIndexRange.h:321
itk::Experimental::IndexRange::const_iterator::MinIndexType
typename std::conditional< VBeginAtZero, ZeroIndex, IndexType >::type MinIndexType
Definition: itkIndexRange.h:268
itk::Experimental::IndexRange::const_iterator::operator==
friend bool operator==(const const_iterator &lhs, const const_iterator &rhs) noexcept
Definition: itkIndexRange.h:186
itk::Size
Represent a n-dimensional size (bounds) of a n-dimensional image.
Definition: itkSize.h:69
itk::Experimental::IndexRange::const_iterator::difference_type
std::ptrdiff_t difference_type
Definition: itkIndexRange.h:91
itk::Experimental::IndexRange::const_iterator::const_iterator
const_iterator(const IndexType &index, const MinIndexType &minIndex, const IndexType &maxIndex) noexcept
Definition: itkIndexRange.h:271
itk::ImageRegion< VDimension >
itk::Experimental::IndexRange::const_iterator::iterator_category
std::bidirectional_iterator_tag iterator_category
Definition: itkIndexRange.h:95
itk::Experimental::IndexRange::MinIndexType
typename iterator::MinIndexType MinIndexType
Definition: itkIndexRange.h:425
itk::Experimental::IndexRange::IndexType
Index< VDimension > IndexType
Definition: itkIndexRange.h:85
itk::Experimental::IndexRange::const_iterator::operator*
reference operator*() const noexcept
Definition: itkIndexRange.h:106
itk::Experimental::IndexRange::const_iterator::operator>
friend bool operator>(const const_iterator &lhs, const const_iterator &rhs) noexcept
Definition: itkIndexRange.h:227
itk::Experimental::IndexRange::const_iterator::ZeroIndex
Definition: itkIndexRange.h:257
itk::Experimental::IndexRange::const_iterator::const_iterator
const_iterator()=default
itk::Experimental::IndexRange::IndexRange
IndexRange(const SizeType &gridSize)
Definition: itkIndexRange.h:307
itkImageRegion.h
itk::Experimental::IndexRange::const_iterator::operator++
const_iterator operator++(int) noexcept
Definition: itkIndexRange.h:139
itk::Experimental::IndexRange::const_iterator::operator<
friend bool operator<(const const_iterator &lhs, const const_iterator &rhs) noexcept
Definition: itkIndexRange.h:205
itk::Experimental::IndexRange::const_iterator::operator--
const_iterator & operator--() noexcept
Definition: itkIndexRange.h:150
itk::Experimental::IndexRange::cend
const_iterator cend() const noexcept
Definition: itkIndexRange.h:364
itk::Experimental::IndexRange::Dimension
constexpr static unsigned Dimension
Definition: itkIndexRange.h:83
itk::Experimental::IndexRange::begin
iterator begin() const noexcept
Definition: itkIndexRange.h:339
itk::Experimental::IndexRange::const_iterator::ZeroIndex::operator[]
constexpr IndexValueType operator[](unsigned) const
Definition: itkIndexRange.h:260
itk::Experimental::IndexRange::rend
reverse_iterator rend() const noexcept
Definition: itkIndexRange.h:378
itk::Index::back
reference back()
Definition: itkIndex.h:453
itk::Experimental::IndexRange::const_iterator
Definition: itkIndexRange.h:87
itk::Experimental::IndexRange::iterator
const_iterator iterator
Definition: itkIndexRange.h:293
itk::Experimental::IndexRange::empty
bool empty() const noexcept
Definition: itkIndexRange.h:414
itkIndex.h
itk::Experimental::IndexRange::m_MaxIndex
IndexType m_MaxIndex
Definition: itkIndexRange.h:460
itk::Experimental::IndexRange::CalculateMaxIndex
static IndexType CalculateMaxIndex(const MinIndexType &minIndex, const SizeType &size)
Definition: itkIndexRange.h:428
itk::Experimental::IndexRange::cbegin
const_iterator cbegin() const noexcept
Definition: itkIndexRange.h:357
itk::Index::Filled
static Self Filled(const IndexValueType value)
Definition: itkIndex.h:480
itk
The "itk" namespace contains all Insight Segmentation and Registration Toolkit (ITK) classes....
Definition: itkArray.h:26
itk::Experimental::IndexRange::const_reverse_iterator
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: itkIndexRange.h:295
itk::Experimental::IndexRange::m_MinIndex
MinIndexType m_MinIndex
Definition: itkIndexRange.h:457
itk::IndexValueType
signed long IndexValueType
Definition: itkIntTypes.h:90
itk::Experimental::IndexRange::crend
const_reverse_iterator crend() const noexcept
Definition: itkIndexRange.h:392
itk::Experimental::IndexRange::const_iterator::m_MaxIndex
IndexType m_MaxIndex
Definition: itkIndexRange.h:290
itk::Experimental::IndexRange::const_iterator::operator<=
friend bool operator<=(const const_iterator &lhs, const const_iterator &rhs) noexcept
Definition: itkIndexRange.h:236
itk::Experimental::IndexRange::IndexRange
IndexRange()=default
itk::Experimental::IndexRange::const_iterator::operator>=
friend bool operator>=(const const_iterator &lhs, const const_iterator &rhs) noexcept
Definition: itkIndexRange.h:245
itk::Experimental::IndexRange::rbegin
reverse_iterator rbegin() const noexcept
Definition: itkIndexRange.h:371
itk::Experimental::IndexRange::const_iterator::operator!=
friend bool operator!=(const const_iterator &lhs, const const_iterator &rhs) noexcept
Definition: itkIndexRange.h:196
itk::Experimental::IndexRange
Definition: itkIndexRange.h:80
itk::Experimental::IndexRange::const_iterator::operator->
pointer operator->() const noexcept
Definition: itkIndexRange.h:110
itkSize.h