ITK 6.0.0
Insight Toolkit
 
Loading...
Searching...
No Matches
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
31namespace itk
32{
33
77template <unsigned int VDimension, bool VBeginAtZero>
78class IndexRange final
79{
80public:
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];
126
127 ++indexValue;
128
129 if (indexValue <= m_MaxIndex[i])
130 {
131 return *this;
132 }
133 indexValue = m_MinIndex[i];
134 }
135 ++m_Index.back();
136
137 return *this;
138 }
139
140
143 constexpr const_iterator
144 operator++(int) noexcept
145 {
146 auto result = *this;
147 ++(*this);
148 return result;
149 }
150
151
153 constexpr const_iterator &
154 operator--() noexcept
155 {
156 for (unsigned int i = 0; i < (VDimension - 1); ++i)
157 {
158 auto & indexValue = m_Index[i];
159
160 --indexValue;
161
162 if (indexValue >= m_MinIndex[i])
163 {
164 return *this;
165 }
166 indexValue = m_MaxIndex[i];
167 }
168 --m_Index.back();
169 return *this;
170 }
171
172
175 constexpr const_iterator
176 operator--(int) noexcept
177 {
178 auto result = *this;
179 --(*this);
180 return result;
181 }
182
183
187 friend bool
188 operator==(const const_iterator & lhs, const const_iterator & rhs) noexcept
189 {
190 assert(lhs.m_MaxIndex == rhs.m_MaxIndex);
191
192 return lhs.m_Index == rhs.m_Index;
193 }
194
195
197 friend bool
198 operator!=(const const_iterator & lhs, const const_iterator & rhs) noexcept
199 {
200 // Implemented just like the corresponding std::rel_ops operator.
201 return !(lhs == rhs);
202 }
203
204
206 friend constexpr bool
207 operator<(const const_iterator & lhs, const const_iterator & rhs) noexcept
208 {
209 for (unsigned int i = VDimension; i > 0; --i)
210 {
211 const auto difference = lhs.m_Index[i - 1] - rhs.m_Index[i - 1];
212
213 if (difference < 0)
214 {
215 return true;
216 }
217 if (difference > 0)
218 {
219 break;
220 }
221 }
222 return false;
223 }
224
225
227 friend constexpr bool
228 operator>(const const_iterator & lhs, const const_iterator & rhs) noexcept
229 {
230 // Implemented just like the corresponding std::rel_ops operator.
231 return rhs < lhs;
232 }
233
234
236 friend constexpr bool
237 operator<=(const const_iterator & lhs, const const_iterator & rhs) noexcept
238 {
239 // Implemented just like the corresponding std::rel_ops operator.
240 return !(rhs < lhs);
241 }
242
243
245 friend constexpr bool
246 operator>=(const const_iterator & lhs, const const_iterator & rhs) noexcept
247 {
248 // Implemented just like the corresponding std::rel_ops operator.
249 return !(lhs < rhs);
250 }
251
252
253 private:
254 friend class IndexRange;
255
256 // Represents an N-dimensional index that is always zero
257 // Aims towards zero runtime overhead.
259 {
260 // The "index" operator.
261 constexpr IndexValueType
262 operator[](unsigned int) const
263 {
264 return 0;
265 }
266
267 // Implicitly converts to a default-initialized itk::Index<N>.
268 constexpr
269 operator IndexType() const
270 {
271 return IndexType();
272 }
273 };
274
275
276 // When BeginAtZero is true, use zero as minimum index, otherwise use itk::Index<N>.
277 using MinIndexType = std::conditional_t<VBeginAtZero, ZeroIndex, IndexType>;
278
279 // Private constructor, only used by friend class IndexRange.
280 constexpr const_iterator(const IndexType & index,
281 const MinIndexType & minIndex,
282 const IndexType & maxIndex) noexcept
283 : // Note: Use parentheses instead of curly braces to initialize data members,
284 // to avoid AppleClang 6.0.0.6000056 compilation error, "no viable conversion..."
285 m_Index(index)
286 , m_MinIndex(minIndex)
287 , m_MaxIndex(maxIndex)
288 {}
289
290
291 // IndexRange::const_iterator data members:
292
293 // Current (N-dimensional) index.
295
296 // Minimum (N-dimensional) index.
298
299 // Maximum (N-dimensional) index.
301 };
302
304 using reverse_iterator = std::reverse_iterator<iterator>;
305 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
306
312 IndexRange() = default;
313
314
317 constexpr explicit IndexRange(const SizeType & gridSize)
318 : // Note: Use parentheses instead of curly braces to initialize data members,
319 // to avoid AppleClang 6.0.0.6000056 compile errors, "no viable conversion..."
320 m_MinIndex()
321 , m_MaxIndex(CalculateMaxIndex(typename iterator::MinIndexType(), gridSize))
322 {}
323
324
329 template <bool VIsSubstitutionFailure = VBeginAtZero,
330 typename TVoid = std::enable_if_t<!VIsSubstitutionFailure>>
331 explicit IndexRange(const ImageRegion<VDimension> & imageRegion)
332 : // Note: Use parentheses instead of curly braces to initialize data members,
333 // to avoid AppleClang 6.0.0.6000056 compile errors, "no viable conversion..."
334 m_MinIndex(imageRegion.GetIndex())
335 , m_MaxIndex(CalculateMaxIndex(imageRegion.GetIndex(), imageRegion.GetSize()))
336 {
337 // Three compile-time asserts, just to check if SFINAE worked properly:
338 static_assert(!VIsSubstitutionFailure,
339 "This template should (of course) be instantiated without substitution failure.");
340 static_assert(std::is_same_v<TVoid, void>,
341 "std::enable_if<!VIsSubstitutionFailure> should yield void, by definition.");
342 static_assert(!VBeginAtZero, "This constructor should only be is available when VBeginAtZero is false.");
343 }
344
345
347 constexpr iterator
348 begin() const noexcept
349 {
351 }
352
354 constexpr iterator
355 end() const noexcept
356 {
357 IndexType index = m_MinIndex;
358 index.back() = m_MaxIndex.back() + 1;
359 return iterator(index, m_MinIndex, m_MaxIndex);
360 }
361
364 constexpr const_iterator
365 cbegin() const noexcept
366 {
367 return this->begin();
368 }
369
371 constexpr const_iterator
372 cend() const noexcept
373 {
374 return this->end();
375 }
376
379 rbegin() const noexcept
380 {
381 return reverse_iterator(this->end());
382 }
383
386 rend() const noexcept
387 {
388 return reverse_iterator(this->begin());
389 }
390
393 crbegin() const noexcept
394 {
395 return this->rbegin();
396 }
397
400 crend() const noexcept
401 {
402 return this->rend();
403 }
404
405
407 constexpr size_t
408 size() const noexcept
409 {
410 size_t result = 1;
411
412 for (unsigned int i = 0; i < VDimension; ++i)
413 {
414 result *= ((m_MaxIndex[i] + 1) - m_MinIndex[i]);
415 }
416 return result;
417 }
418
419
421 constexpr bool
422 empty() const noexcept
423 {
424 // When an IndexRange is empty, each index value of m_MaxIndex is less than the corresponding
425 // index value of m_MinIndex. And vice versa: when an IndexRange is non-empty, each index value
426 // of m_MaxIndex is greater than or equal to the corresponding index value of m_MinIndex.
427 // Note that the range contains one element when m_MaxIndex == m_MinIndex.
428 return m_MaxIndex[0] < m_MinIndex[0];
429 }
430
431
432private:
434
435 static constexpr IndexType
436 CalculateMaxIndex(const MinIndexType & minIndex, const SizeType & size)
437 {
438 const bool sizeHasZeroValue = [&size] {
439 for (const auto sizeValue : size)
440 {
441 if (sizeValue == 0)
442 {
443 return true;
444 }
445 }
446 return false;
447 }();
448
449 // Treat any size that has a zero value equally.
450 const SizeType normalizedSize = sizeHasZeroValue ? SizeType{ { 0 } } : size;
451
452 // The `index` is initialized (`{}`), just to support C++17 constexpr.
453 IndexType index{};
454
455 for (unsigned int i = 0; i < VDimension; ++i)
456 {
457 index[i] = minIndex[i] + static_cast<IndexValueType>(normalizedSize[i]) - 1;
458 }
459
460 return index;
461 }
462
463 // IndexRange data members:
464
465 // Minimum (N-dimensional) index.
467
468 // Maximum (N-dimensional) index.
470};
471
472template <unsigned int VDimension>
474
475template <unsigned int VDimension>
477
478} // namespace itk
479
480#endif
An image region represents a structured region of data.
friend bool operator!=(const const_iterator &lhs, const const_iterator &rhs) noexcept
friend constexpr bool operator>=(const const_iterator &lhs, const const_iterator &rhs) noexcept
friend constexpr bool operator<=(const const_iterator &lhs, const const_iterator &rhs) noexcept
constexpr const_iterator & operator--() noexcept
std::bidirectional_iterator_tag iterator_category
friend constexpr bool operator<(const const_iterator &lhs, const const_iterator &rhs) noexcept
constexpr reference operator*() const noexcept
constexpr pointer operator->() const noexcept
constexpr const_iterator(const IndexType &index, const MinIndexType &minIndex, const IndexType &maxIndex) noexcept
friend bool operator==(const const_iterator &lhs, const const_iterator &rhs) noexcept
std::conditional_t< VBeginAtZero, ZeroIndex, IndexType > MinIndexType
constexpr const_iterator & operator++() noexcept
constexpr const_iterator operator++(int) noexcept
constexpr const_iterator operator--(int) noexcept
friend constexpr bool operator>(const const_iterator &lhs, const const_iterator &rhs) noexcept
const_reverse_iterator crend() const noexcept
Index< VDimension > IndexType
std::reverse_iterator< const_iterator > const_reverse_iterator
constexpr bool empty() const noexcept
Size< VDimension > SizeType
const_reverse_iterator crbegin() const noexcept
constexpr iterator end() const noexcept
constexpr vcl_size_t size() const noexcept
IndexRange(const ImageRegion< VDimension > &imageRegion)
std::reverse_iterator< iterator > reverse_iterator
static constexpr IndexType CalculateMaxIndex(const MinIndexType &minIndex, const SizeType &size)
constexpr const_iterator cend() const noexcept
const_iterator iterator
reverse_iterator rbegin() const noexcept
reverse_iterator rend() const noexcept
constexpr iterator begin() const noexcept
constexpr const_iterator cbegin() const noexcept
constexpr IndexRange(const SizeType &gridSize)
IndexRange()=default
The "itk" namespace contains all Insight Segmentation and Registration Toolkit (ITK) classes....
IndexRange< VDimension, true > ZeroBasedIndexRange
IndexRange< VDimension, false > ImageRegionIndexRange
long IndexValueType
Definition itkIntTypes.h:93
constexpr IndexValueType operator[](unsigned int) const
Represent a n-dimensional index in a n-dimensional image.
Definition itkIndex.h:69
static constexpr Self Filled(const IndexValueType value)
Definition itkIndex.h:496
constexpr reference back()
Definition itkIndex.h:469
Represent a n-dimensional size (bounds) of a n-dimensional image.
Definition itkSize.h:70