ITK  6.0.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  * https://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 
77 template <unsigned int VDimension, bool VBeginAtZero>
78 class IndexRange final
79 {
80 public:
81  static constexpr unsigned int Dimension = VDimension;
84 
85  class const_iterator final
86  {
87  public:
88  // Types conforming the iterator requirements of the C++ standard library:
89  using difference_type = ptrdiff_t;
91  using reference = const IndexType &;
92  using pointer = const IndexType *;
93  using iterator_category = std::bidirectional_iterator_tag;
94 
100  const_iterator() = default;
101 
102 
104  constexpr reference operator*() const noexcept { return m_Index; }
105 
106 
108  constexpr pointer operator->() const noexcept { return &(**this); }
109 
110 
112  constexpr const_iterator &
113  operator++() noexcept
114  {
115  for (unsigned int i = 0; i < (VDimension - 1); ++i)
116  {
117  auto & indexValue = m_Index[i];
120  ++indexValue;
121 
122  if (indexValue <= m_MaxIndex[i])
123  {
124  return *this;
125  }
126  indexValue = m_MinIndex[i];
127  }
128  ++m_Index.back();
129 
130  return *this;
131  }
132 
133 
136  constexpr const_iterator
137  operator++(int) noexcept
138  {
139  auto result = *this;
140  ++(*this);
141  return result;
142  }
147  constexpr const_iterator &
148  operator--() noexcept
149  {
150  for (unsigned int i = 0; i < (VDimension - 1); ++i)
151  {
152  auto & indexValue = m_Index[i];
155  --indexValue;
156 
157  if (indexValue >= m_MinIndex[i])
158  {
159  return *this;
160  }
161  indexValue = m_MaxIndex[i];
162  }
163  --m_Index.back();
164  return *this;
165  }
166 
167 
170  constexpr const_iterator
171  operator--(int) noexcept
172  {
173  auto result = *this;
174  --(*this);
175  return result;
176  }
183  friend bool
184  operator==(const const_iterator & lhs, const const_iterator & rhs) noexcept
185  {
186  assert(lhs.m_MaxIndex == rhs.m_MaxIndex);
187 
188  return lhs.m_Index == rhs.m_Index;
189  }
190 
191 
193  friend bool
194  operator!=(const const_iterator & lhs, const const_iterator & rhs) noexcept
195  {
196  // Implemented just like the corresponding std::rel_ops operator.
197  return !(lhs == rhs);
198  }
199 
200 
202  friend constexpr bool
203  operator<(const const_iterator & lhs, const const_iterator & rhs) noexcept
204  {
205  for (unsigned int i = VDimension; i > 0; --i)
206  {
207  const auto difference = lhs.m_Index[i - 1] - rhs.m_Index[i - 1];
210  if (difference < 0)
211  {
212  return true;
213  }
214  if (difference > 0)
215  {
216  break;
217  }
218  }
219  return false;
220  }
221 
222 
224  friend constexpr bool
225  operator>(const const_iterator & lhs, const const_iterator & rhs) noexcept
226  {
227  // Implemented just like the corresponding std::rel_ops operator.
228  return rhs < lhs;
229  }
230 
231 
233  friend constexpr bool
234  operator<=(const const_iterator & lhs, const const_iterator & rhs) noexcept
235  {
236  // Implemented just like the corresponding std::rel_ops operator.
237  return !(rhs < lhs);
238  }
239 
240 
242  friend constexpr bool
243  operator>=(const const_iterator & lhs, const const_iterator & rhs) noexcept
244  {
245  // Implemented just like the corresponding std::rel_ops operator.
246  return !(lhs < rhs);
247  }
248 
249 
250  private:
251  friend class IndexRange;
252 
253  // Represents an N-dimensional index that is always zero
254  // Aims towards zero runtime overhead.
255  struct ZeroIndex
256  {
257  // The "index" operator.
258  constexpr IndexValueType operator[](unsigned int) const { return 0; }
259 
260  // Implicitly converts to a default-initialized itk::Index<N>.
261  constexpr operator IndexType() const { return IndexType(); }
262  };
263 
264 
265  // When BeginAtZero is true, use zero as minimum index, otherwise use itk::Index<N>.
266  using MinIndexType = std::conditional_t<VBeginAtZero, ZeroIndex, IndexType>;
267 
268  // Private constructor, only used by friend class IndexRange.
269  constexpr const_iterator(const IndexType & index,
270  const MinIndexType & minIndex,
271  const IndexType & maxIndex) noexcept
272  : // Note: Use parentheses instead of curly braces to initialize data members,
273  // to avoid AppleClang 6.0.0.6000056 compilation error, "no viable conversion..."
274  m_Index(index)
275  , m_MinIndex(minIndex)
276  , m_MaxIndex(maxIndex)
277  {}
278 
279 
280  // IndexRange::const_iterator data members:
281 
282  // Current (N-dimensional) index.
284 
285  // Minimum (N-dimensional) index.
287 
288  // Maximum (N-dimensional) index.
290  };
291 
293  using reverse_iterator = std::reverse_iterator<iterator>;
294  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
295 
301  IndexRange() = default;
302 
303 
306  constexpr explicit IndexRange(const SizeType & gridSize)
307  : // Note: Use parentheses instead of curly braces to initialize data members,
308  // to avoid AppleClang 6.0.0.6000056 compile errors, "no viable conversion..."
309  m_MinIndex()
310  , m_MaxIndex(CalculateMaxIndex(typename iterator::MinIndexType(), gridSize))
311  {}
312 
313 
318  template <bool VIsSubstitutionFailure = VBeginAtZero,
319  typename TVoid = std::enable_if_t<!VIsSubstitutionFailure>>
320  explicit IndexRange(const ImageRegion<VDimension> & imageRegion)
321  : // Note: Use parentheses instead of curly braces to initialize data members,
322  // to avoid AppleClang 6.0.0.6000056 compile errors, "no viable conversion..."
323  m_MinIndex(imageRegion.GetIndex())
324  , m_MaxIndex(CalculateMaxIndex(imageRegion.GetIndex(), imageRegion.GetSize()))
325  {
326  // Three compile-time asserts, just to check if SFINAE worked properly:
327  static_assert(!VIsSubstitutionFailure,
328  "This template should (of course) be instantiated without substitution failure.");
329  static_assert(std::is_same_v<TVoid, void>,
330  "std::enable_if<!VIsSubstitutionFailure> should yield void, by definition.");
331  static_assert(!VBeginAtZero, "This constructor should only be is available when VBeginAtZero is false.");
332  }
337  constexpr iterator
338  begin() const noexcept
339  {
341  }
342 
344  constexpr iterator
345  end() const noexcept
346  {
347  IndexType index = m_MinIndex;
348  index.back() = m_MaxIndex.back() + 1;
349  return iterator(index, m_MinIndex, m_MaxIndex);
350  }
355  constexpr const_iterator
356  cbegin() const noexcept
357  {
358  return this->begin();
359  }
360 
362  constexpr const_iterator
363  cend() const noexcept
364  {
365  return this->end();
366  }
367 
370  rbegin() const noexcept
371  {
372  return reverse_iterator(this->end());
373  }
374 
377  rend() const noexcept
378  {
379  return reverse_iterator(this->begin());
380  }
381 
384  crbegin() const noexcept
385  {
386  return this->rbegin();
387  }
388 
391  crend() const noexcept
392  {
393  return this->rend();
394  }
395 
396 
398  constexpr size_t
399  size() const noexcept
400  {
401  size_t result = 1;
402 
403  for (unsigned int i = 0; i < VDimension; ++i)
404  {
405  result *= ((m_MaxIndex[i] + 1) - m_MinIndex[i]);
406  }
407  return result;
408  }
409 
410 
412  constexpr bool
413  empty() const noexcept
414  {
415  // When an IndexRange is empty, each index value of m_MaxIndex is less than the corresponding
416  // index value of m_MinIndex. And vice versa: when an IndexRange is non-empty, each index value
417  // of m_MaxIndex is greater than or equal to the corresponding index value of m_MinIndex.
418  // Note that the range contains one element when m_MaxIndex == m_MinIndex.
419  return m_MaxIndex[0] < m_MinIndex[0];
420  }
421 
422 
423 private:
425 
426  static constexpr IndexType
427  CalculateMaxIndex(const MinIndexType & minIndex, const SizeType & size)
428  {
429  const bool sizeHasZeroValue = [&size] {
430  for (const auto sizeValue : size)
431  {
432  if (sizeValue == 0)
433  {
434  return true;
435  }
436  }
437  return false;
438  }();
439 
440  // Treat any size that has a zero value equally.
441  const SizeType normalizedSize = sizeHasZeroValue ? SizeType{ { 0 } } : size;
442 
443  // The `index` is initialized (`{}`), just to support C++17 constexpr.
444  IndexType index{};
445 
446  for (unsigned int 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 int VDimension>
465 
466 template <unsigned int VDimension>
468 
469 } // namespace itk
470 
471 #endif
itk::Index
Represent a n-dimensional index in a n-dimensional image.
Definition: itkIndex.h:68
itk::IndexRange::size
constexpr vcl_size_t size() const noexcept
Definition: itkIndexRange.h:399
itk::IndexRange::const_iterator::operator>
constexpr friend bool operator>(const const_iterator &lhs, const const_iterator &rhs) noexcept
Definition: itkIndexRange.h:225
itk::IndexRange::rbegin
reverse_iterator rbegin() const noexcept
Definition: itkIndexRange.h:370
itk::IndexRange::const_iterator::ZeroIndex
Definition: itkIndexRange.h:255
itk::IndexRange::const_iterator::operator--
constexpr const_iterator & operator--() noexcept
Definition: itkIndexRange.h:148
itk::Size
Represent a n-dimensional size (bounds) of a n-dimensional image.
Definition: itkSize.h:69
itk::Index::back
constexpr reference back()
Definition: itkIndex.h:467
itk::IndexRange::const_iterator::operator--
constexpr const_iterator operator--(int) noexcept
Definition: itkIndexRange.h:171
itk::IndexRange::const_iterator::operator>=
constexpr friend bool operator>=(const const_iterator &lhs, const const_iterator &rhs) noexcept
Definition: itkIndexRange.h:243
itk::IndexRange::const_iterator::MinIndexType
std::conditional_t< VBeginAtZero, ZeroIndex, IndexType > MinIndexType
Definition: itkIndexRange.h:266
itk::IndexRange::const_iterator::operator++
constexpr const_iterator operator++(int) noexcept
Definition: itkIndexRange.h:137
itk::IndexRange::const_iterator
Definition: itkIndexRange.h:85
itk::ImageRegion< VDimension >
itk::IndexRange::end
constexpr iterator end() const noexcept
Definition: itkIndexRange.h:345
itk::IndexRange::const_iterator::difference_type
ptrdiff_t difference_type
Definition: itkIndexRange.h:89
itk::IndexRange::const_iterator::m_MinIndex
MinIndexType m_MinIndex
Definition: itkIndexRange.h:286
itk::IndexRange::crend
const_reverse_iterator crend() const noexcept
Definition: itkIndexRange.h:391
itk::IndexRange::IndexType
Index< VDimension > IndexType
Definition: itkIndexRange.h:83
itk::IndexRange::m_MaxIndex
IndexType m_MaxIndex
Definition: itkIndexRange.h:460
itk::IndexRange::const_iterator::operator<
constexpr friend bool operator<(const const_iterator &lhs, const const_iterator &rhs) noexcept
Definition: itkIndexRange.h:203
itk::IndexRange::const_iterator::const_iterator
constexpr const_iterator(const IndexType &index, const MinIndexType &minIndex, const IndexType &maxIndex) noexcept
Definition: itkIndexRange.h:269
itkImageRegion.h
itk::IndexValueType
long IndexValueType
Definition: itkIntTypes.h:93
itk::IndexRange::begin
constexpr iterator begin() const noexcept
Definition: itkIndexRange.h:338
itk::IndexRange::cend
constexpr const_iterator cend() const noexcept
Definition: itkIndexRange.h:363
itk::IndexRange::const_reverse_iterator
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: itkIndexRange.h:294
itk::IndexRange::crbegin
const_reverse_iterator crbegin() const noexcept
Definition: itkIndexRange.h:384
itk::IndexRange::IndexRange
IndexRange(const ImageRegion< VDimension > &imageRegion)
Definition: itkIndexRange.h:320
itk::IndexRange::reverse_iterator
std::reverse_iterator< iterator > reverse_iterator
Definition: itkIndexRange.h:293
itk::IndexRange::const_iterator::const_iterator
const_iterator()=default
itk::IndexRange::const_iterator::operator!=
friend bool operator!=(const const_iterator &lhs, const const_iterator &rhs) noexcept
Definition: itkIndexRange.h:194
itk::IndexRange::cbegin
constexpr const_iterator cbegin() const noexcept
Definition: itkIndexRange.h:356
itk::IndexRange::const_iterator::operator*
constexpr reference operator*() const noexcept
Definition: itkIndexRange.h:104
itkIndex.h
itk::IndexRange::const_iterator::operator->
constexpr pointer operator->() const noexcept
Definition: itkIndexRange.h:108
itk::IndexRange::IndexRange
constexpr IndexRange(const SizeType &gridSize)
Definition: itkIndexRange.h:306
itk::IndexRange::IndexRange
IndexRange()=default
itk::Index::Filled
static constexpr Self Filled(const IndexValueType value)
Definition: itkIndex.h:494
itk::IndexRange::const_iterator::m_MaxIndex
IndexType m_MaxIndex
Definition: itkIndexRange.h:289
itk::IndexRange::rend
reverse_iterator rend() const noexcept
Definition: itkIndexRange.h:377
itk
The "itk" namespace contains all Insight Segmentation and Registration Toolkit (ITK) classes....
Definition: itkAnnulusOperator.h:24
itk::IndexRange::const_iterator::iterator_category
std::bidirectional_iterator_tag iterator_category
Definition: itkIndexRange.h:93
itk::IndexRange::empty
constexpr bool empty() const noexcept
Definition: itkIndexRange.h:413
itk::IndexRange::const_iterator::operator==
friend bool operator==(const const_iterator &lhs, const const_iterator &rhs) noexcept
Definition: itkIndexRange.h:184
itk::IndexRange::m_MinIndex
MinIndexType m_MinIndex
Definition: itkIndexRange.h:457
itk::IndexRange::MinIndexType
typename iterator::MinIndexType MinIndexType
Definition: itkIndexRange.h:424
itk::IndexRange::iterator
const_iterator iterator
Definition: itkIndexRange.h:292
itk::IndexRange::const_iterator::ZeroIndex::operator[]
constexpr IndexValueType operator[](unsigned int) const
Definition: itkIndexRange.h:258
itk::IndexRange
Definition: itkIndexRange.h:78
itk::IndexRange::const_iterator::m_Index
IndexType m_Index
Definition: itkIndexRange.h:283
itk::IndexRange::const_iterator::operator++
constexpr const_iterator & operator++() noexcept
Definition: itkIndexRange.h:113
itk::IndexRange::CalculateMaxIndex
static constexpr IndexType CalculateMaxIndex(const MinIndexType &minIndex, const SizeType &size)
Definition: itkIndexRange.h:427
itk::IndexRange::const_iterator::operator<=
constexpr friend bool operator<=(const const_iterator &lhs, const const_iterator &rhs) noexcept
Definition: itkIndexRange.h:234
itkSize.h
itk::IndexRange::Dimension
static constexpr unsigned int Dimension
Definition: itkIndexRange.h:81