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
105  operator*() const noexcept
106  {
107  return m_Index;
108  }
109 
110 
112  constexpr pointer
113  operator->() const noexcept
114  {
115  return &(**this);
116  }
117 
118 
120  constexpr const_iterator &
121  operator++() noexcept
122  {
123  for (unsigned int i = 0; i < (VDimension - 1); ++i)
124  {
125  auto & indexValue = m_Index[i];
128  ++indexValue;
129 
130  if (indexValue <= m_MaxIndex[i])
131  {
132  return *this;
133  }
134  indexValue = m_MinIndex[i];
135  }
136  ++m_Index.back();
137 
138  return *this;
139  }
140 
141 
144  constexpr const_iterator
145  operator++(int) noexcept
146  {
147  auto result = *this;
148  ++(*this);
149  return result;
150  }
155  constexpr const_iterator &
156  operator--() noexcept
157  {
158  for (unsigned int i = 0; i < (VDimension - 1); ++i)
159  {
160  auto & indexValue = m_Index[i];
163  --indexValue;
164 
165  if (indexValue >= m_MinIndex[i])
166  {
167  return *this;
168  }
169  indexValue = m_MaxIndex[i];
170  }
171  --m_Index.back();
172  return *this;
173  }
174 
175 
178  constexpr const_iterator
179  operator--(int) noexcept
180  {
181  auto result = *this;
182  --(*this);
183  return result;
184  }
191  friend bool
192  operator==(const const_iterator & lhs, const const_iterator & rhs) noexcept
193  {
194  assert(lhs.m_MaxIndex == rhs.m_MaxIndex);
195 
196  return lhs.m_Index == rhs.m_Index;
197  }
198 
199 
201  friend bool
202  operator!=(const const_iterator & lhs, const const_iterator & rhs) noexcept
203  {
204  // Implemented just like the corresponding std::rel_ops operator.
205  return !(lhs == rhs);
206  }
207 
208 
210  friend constexpr bool
211  operator<(const const_iterator & lhs, const const_iterator & rhs) noexcept
212  {
213  for (unsigned int i = VDimension; i > 0; --i)
214  {
215  const auto difference = lhs.m_Index[i - 1] - rhs.m_Index[i - 1];
218  if (difference < 0)
219  {
220  return true;
221  }
222  if (difference > 0)
223  {
224  break;
225  }
226  }
227  return false;
228  }
229 
230 
232  friend constexpr bool
233  operator>(const const_iterator & lhs, const const_iterator & rhs) noexcept
234  {
235  // Implemented just like the corresponding std::rel_ops operator.
236  return rhs < lhs;
237  }
238 
239 
241  friend constexpr bool
242  operator<=(const const_iterator & lhs, const const_iterator & rhs) noexcept
243  {
244  // Implemented just like the corresponding std::rel_ops operator.
245  return !(rhs < lhs);
246  }
247 
248 
250  friend constexpr bool
251  operator>=(const const_iterator & lhs, const const_iterator & rhs) noexcept
252  {
253  // Implemented just like the corresponding std::rel_ops operator.
254  return !(lhs < rhs);
255  }
256 
257 
258  private:
259  friend class IndexRange;
260 
261  // Represents an N-dimensional index that is always zero
262  // Aims towards zero runtime overhead.
263  struct ZeroIndex
264  {
265  // The "index" operator.
266  constexpr IndexValueType
267  operator[](unsigned int) const
268  {
269  return 0;
270  }
271 
272  // Implicitly converts to a default-initialized itk::Index<N>.
273  constexpr
274  operator IndexType() const
275  {
276  return IndexType();
277  }
278  };
279 
280 
281  // When BeginAtZero is true, use zero as minimum index, otherwise use itk::Index<N>.
282  using MinIndexType = std::conditional_t<VBeginAtZero, ZeroIndex, IndexType>;
283 
284  // Private constructor, only used by friend class IndexRange.
285  constexpr const_iterator(const IndexType & index,
286  const MinIndexType & minIndex,
287  const IndexType & maxIndex) noexcept
288  : // Note: Use parentheses instead of curly braces to initialize data members,
289  // to avoid AppleClang 6.0.0.6000056 compilation error, "no viable conversion..."
290  m_Index(index)
291  , m_MinIndex(minIndex)
292  , m_MaxIndex(maxIndex)
293  {}
294 
295 
296  // IndexRange::const_iterator data members:
297 
298  // Current (N-dimensional) index.
300 
301  // Minimum (N-dimensional) index.
303 
304  // Maximum (N-dimensional) index.
306  };
307 
309  using reverse_iterator = std::reverse_iterator<iterator>;
310  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
311 
317  IndexRange() = default;
318 
319 
322  constexpr explicit IndexRange(const SizeType & gridSize)
323  : // Note: Use parentheses instead of curly braces to initialize data members,
324  // to avoid AppleClang 6.0.0.6000056 compile errors, "no viable conversion..."
325  m_MinIndex()
326  , m_MaxIndex(CalculateMaxIndex(typename iterator::MinIndexType(), gridSize))
327  {}
328 
329 
334  template <bool VIsSubstitutionFailure = VBeginAtZero,
335  typename TVoid = std::enable_if_t<!VIsSubstitutionFailure>>
336  explicit IndexRange(const ImageRegion<VDimension> & imageRegion)
337  : // Note: Use parentheses instead of curly braces to initialize data members,
338  // to avoid AppleClang 6.0.0.6000056 compile errors, "no viable conversion..."
339  m_MinIndex(imageRegion.GetIndex())
340  , m_MaxIndex(CalculateMaxIndex(imageRegion.GetIndex(), imageRegion.GetSize()))
341  {
342  // Three compile-time asserts, just to check if SFINAE worked properly:
343  static_assert(!VIsSubstitutionFailure,
344  "This template should (of course) be instantiated without substitution failure.");
345  static_assert(std::is_same_v<TVoid, void>,
346  "std::enable_if<!VIsSubstitutionFailure> should yield void, by definition.");
347  static_assert(!VBeginAtZero, "This constructor should only be is available when VBeginAtZero is false.");
348  }
353  constexpr iterator
354  begin() const noexcept
355  {
357  }
358 
360  constexpr iterator
361  end() const noexcept
362  {
363  IndexType index = m_MinIndex;
364  index.back() = m_MaxIndex.back() + 1;
365  return iterator(index, m_MinIndex, m_MaxIndex);
366  }
371  constexpr const_iterator
372  cbegin() const noexcept
373  {
374  return this->begin();
375  }
376 
378  constexpr const_iterator
379  cend() const noexcept
380  {
381  return this->end();
382  }
383 
386  rbegin() const noexcept
387  {
388  return reverse_iterator(this->end());
389  }
390 
393  rend() const noexcept
394  {
395  return reverse_iterator(this->begin());
396  }
397 
400  crbegin() const noexcept
401  {
402  return this->rbegin();
403  }
404 
407  crend() const noexcept
408  {
409  return this->rend();
410  }
411 
412 
414  constexpr size_t
415  size() const noexcept
416  {
417  size_t result = 1;
418 
419  for (unsigned int i = 0; i < VDimension; ++i)
420  {
421  result *= ((m_MaxIndex[i] + 1) - m_MinIndex[i]);
422  }
423  return result;
424  }
425 
426 
428  constexpr bool
429  empty() const noexcept
430  {
431  // When an IndexRange is empty, each index value of m_MaxIndex is less than the corresponding
432  // index value of m_MinIndex. And vice versa: when an IndexRange is non-empty, each index value
433  // of m_MaxIndex is greater than or equal to the corresponding index value of m_MinIndex.
434  // Note that the range contains one element when m_MaxIndex == m_MinIndex.
435  return m_MaxIndex[0] < m_MinIndex[0];
436  }
437 
438 
439 private:
441 
442  static constexpr IndexType
443  CalculateMaxIndex(const MinIndexType & minIndex, const SizeType & size)
444  {
445  const bool sizeHasZeroValue = [&size] {
446  for (const auto sizeValue : size)
447  {
448  if (sizeValue == 0)
449  {
450  return true;
451  }
452  }
453  return false;
454  }();
455 
456  // Treat any size that has a zero value equally.
457  const SizeType normalizedSize = sizeHasZeroValue ? SizeType{ { 0 } } : size;
458 
459  // The `index` is initialized (`{}`), just to support C++17 constexpr.
460  IndexType index{};
461 
462  for (unsigned int i = 0; i < VDimension; ++i)
463  {
464  index[i] = minIndex[i] + static_cast<IndexValueType>(normalizedSize[i]) - 1;
465  }
466 
467  return index;
468  }
469 
470  // IndexRange data members:
471 
472  // Minimum (N-dimensional) index.
474 
475  // Maximum (N-dimensional) index.
477 };
478 
479 template <unsigned int VDimension>
481 
482 template <unsigned int VDimension>
484 
485 } // namespace itk
486 
487 #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:415
itk::IndexRange::const_iterator::operator>
constexpr friend bool operator>(const const_iterator &lhs, const const_iterator &rhs) noexcept
Definition: itkIndexRange.h:233
itk::IndexRange::rbegin
reverse_iterator rbegin() const noexcept
Definition: itkIndexRange.h:386
itk::IndexRange::const_iterator::ZeroIndex
Definition: itkIndexRange.h:263
itk::IndexRange::const_iterator::operator--
constexpr const_iterator & operator--() noexcept
Definition: itkIndexRange.h:156
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:476
itk::IndexRange::const_iterator::operator--
constexpr const_iterator operator--(int) noexcept
Definition: itkIndexRange.h:179
itk::IndexRange::const_iterator::operator>=
constexpr friend bool operator>=(const const_iterator &lhs, const const_iterator &rhs) noexcept
Definition: itkIndexRange.h:251
itk::IndexRange::const_iterator::MinIndexType
std::conditional_t< VBeginAtZero, ZeroIndex, IndexType > MinIndexType
Definition: itkIndexRange.h:282
itk::IndexRange::const_iterator::operator++
constexpr const_iterator operator++(int) noexcept
Definition: itkIndexRange.h:145
itk::IndexRange::const_iterator
Definition: itkIndexRange.h:85
itk::ImageRegion< VDimension >
itk::IndexRange::end
constexpr iterator end() const noexcept
Definition: itkIndexRange.h:361
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:302
itk::IndexRange::crend
const_reverse_iterator crend() const noexcept
Definition: itkIndexRange.h:407
itk::IndexRange::IndexType
Index< VDimension > IndexType
Definition: itkIndexRange.h:83
itk::IndexRange::m_MaxIndex
IndexType m_MaxIndex
Definition: itkIndexRange.h:476
itk::IndexRange::const_iterator::operator<
constexpr friend bool operator<(const const_iterator &lhs, const const_iterator &rhs) noexcept
Definition: itkIndexRange.h:211
itk::IndexRange::const_iterator::const_iterator
constexpr const_iterator(const IndexType &index, const MinIndexType &minIndex, const IndexType &maxIndex) noexcept
Definition: itkIndexRange.h:285
itkImageRegion.h
itk::IndexValueType
long IndexValueType
Definition: itkIntTypes.h:93
itk::IndexRange::begin
constexpr iterator begin() const noexcept
Definition: itkIndexRange.h:354
itk::IndexRange::cend
constexpr const_iterator cend() const noexcept
Definition: itkIndexRange.h:379
itk::IndexRange::const_reverse_iterator
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: itkIndexRange.h:310
itk::IndexRange::crbegin
const_reverse_iterator crbegin() const noexcept
Definition: itkIndexRange.h:400
itk::IndexRange::IndexRange
IndexRange(const ImageRegion< VDimension > &imageRegion)
Definition: itkIndexRange.h:336
itk::IndexRange::reverse_iterator
std::reverse_iterator< iterator > reverse_iterator
Definition: itkIndexRange.h:309
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:202
itk::IndexRange::cbegin
constexpr const_iterator cbegin() const noexcept
Definition: itkIndexRange.h:372
itk::IndexRange::const_iterator::pointer
const IndexType * pointer
Definition: itkIndexRange.h:92
itk::IndexRange::const_iterator::operator*
constexpr reference operator*() const noexcept
Definition: itkIndexRange.h:105
itkIndex.h
itk::IndexRange::const_iterator::operator->
constexpr pointer operator->() const noexcept
Definition: itkIndexRange.h:113
itk::IndexRange::IndexRange
constexpr IndexRange(const SizeType &gridSize)
Definition: itkIndexRange.h:322
itk::IndexRange::IndexRange
IndexRange()=default
itk::Index::Filled
static constexpr Self Filled(const IndexValueType value)
Definition: itkIndex.h:503
itk::IndexRange::const_iterator::m_MaxIndex
IndexType m_MaxIndex
Definition: itkIndexRange.h:305
itk::IndexRange::rend
reverse_iterator rend() const noexcept
Definition: itkIndexRange.h:393
itk
The "itk" namespace contains all Insight Segmentation and Registration Toolkit (ITK) classes....
Definition: itkAnatomicalOrientation.h:29
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:429
itk::IndexRange::const_iterator::operator==
friend bool operator==(const const_iterator &lhs, const const_iterator &rhs) noexcept
Definition: itkIndexRange.h:192
itk::IndexRange::m_MinIndex
MinIndexType m_MinIndex
Definition: itkIndexRange.h:473
itk::IndexRange::MinIndexType
typename iterator::MinIndexType MinIndexType
Definition: itkIndexRange.h:440
itk::IndexRange::iterator
const_iterator iterator
Definition: itkIndexRange.h:308
itk::IndexRange::const_iterator::ZeroIndex::operator[]
constexpr IndexValueType operator[](unsigned int) const
Definition: itkIndexRange.h:267
itk::IndexRange
Definition: itkIndexRange.h:78
itk::IndexRange::const_iterator::m_Index
IndexType m_Index
Definition: itkIndexRange.h:299
itk::IndexRange::const_iterator::operator++
constexpr const_iterator & operator++() noexcept
Definition: itkIndexRange.h:121
itk::IndexRange::CalculateMaxIndex
static constexpr IndexType CalculateMaxIndex(const MinIndexType &minIndex, const SizeType &size)
Definition: itkIndexRange.h:443
itk::IndexRange::const_iterator::operator<=
constexpr friend bool operator<=(const const_iterator &lhs, const const_iterator &rhs) noexcept
Definition: itkIndexRange.h:242
itkSize.h
itk::IndexRange::Dimension
static constexpr unsigned int Dimension
Definition: itkIndexRange.h:81