ITK  5.3.0
Insight Toolkit
itkIndex.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 #ifndef itkIndex_h
19 #define itkIndex_h
20 
21 #include "itkOffset.h"
22 #include <type_traits> // For is_integral.
23 
24 namespace itk
25 {
26 
65 
66 template <unsigned int VDimension = 2>
67 struct ITK_TEMPLATE_EXPORT Index final
68 {
69 public:
70  // Using the `rule of zero` to this aggregate type
71  // C++20 changes the definition of aggregate such that classes with any user-declared ctors are no longer aggregates.
72 
74  using Self = Index;
75 
79 
82 
86 
88  static constexpr unsigned int Dimension = VDimension;
89 
91  static constexpr unsigned int
93  {
94  return VDimension;
95  }
96 
97 
99  const Self
100  operator+(const SizeType & sz) const
101  {
102  Self result;
103 
104  for (unsigned int i = 0; i < VDimension; ++i)
105  {
106  result[i] = m_InternalArray[i] + static_cast<IndexValueType>(sz[i]);
107  }
108  return result;
109  }
110 
112  const Self &
113  operator+=(const SizeType & sz)
114  {
115  for (unsigned int i = 0; i < VDimension; ++i)
116  {
117  m_InternalArray[i] += static_cast<IndexValueType>(sz[i]);
118  }
119  return *this;
120  }
122 
125  const Self
126  operator-(const SizeType & sz) const
127  {
128  Self result;
129 
130  for (unsigned int i = 0; i < VDimension; ++i)
131  {
132  result[i] = m_InternalArray[i] - static_cast<IndexValueType>(sz[i]);
133  }
134  return result;
135  }
136 
138  const Self &
139  operator-=(const SizeType & sz)
140  {
141  for (unsigned int i = 0; i < VDimension; ++i)
142  {
143  m_InternalArray[i] -= static_cast<IndexValueType>(sz[i]);
144  }
145  return *this;
146  }
148 
150  const Self
151  operator+(const OffsetType & offset) const
152  {
153  Self result;
154 
155  for (unsigned int i = 0; i < VDimension; ++i)
156  {
157  result[i] = m_InternalArray[i] + offset[i];
158  }
159  return result;
160  }
161 
163  const Self &
164  operator+=(const OffsetType & offset)
165  {
166  for (unsigned int i = 0; i < VDimension; ++i)
167  {
168  m_InternalArray[i] += offset[i];
169  }
170  return *this;
171  }
173 
175  const Self &
176  operator-=(const OffsetType & offset)
177  {
178  for (unsigned int i = 0; i < VDimension; ++i)
179  {
180  m_InternalArray[i] -= offset[i];
181  }
182  return *this;
183  }
185 
187  const Self
188  operator-(const OffsetType & off) const
189  {
190  Self result;
191 
192  for (unsigned int i = 0; i < VDimension; ++i)
193  {
194  result[i] = m_InternalArray[i] - off.m_InternalArray[i];
195  }
196  return result;
197  }
198 
200  const OffsetType
201  operator-(const Self & vec) const
202  {
203  OffsetType result;
204 
205  for (unsigned int i = 0; i < VDimension; ++i)
206  {
207  result[i] = m_InternalArray[i] - vec.m_InternalArray[i];
208  }
209  return result;
210  }
211 
215  const Self operator*(const SizeType & vec) const
216  {
217  Self result;
218 
219  for (unsigned int i = 0; i < VDimension; ++i)
220  {
221  result[i] = m_InternalArray[i] * static_cast<IndexValueType>(vec.m_InternalArray[i]);
222  }
223  return result;
224  }
225 
228  const IndexValueType *
229  GetIndex() const
230  {
231  return m_InternalArray;
232  }
233 
238  void
239  SetIndex(const IndexValueType val[VDimension])
240  {
241  std::copy_n(val, VDimension, m_InternalArray);
242  }
243 
250  void
251  SetElement(unsigned long element, IndexValueType val)
252  {
253  m_InternalArray[element] = val;
254  }
255 
263  GetElement(unsigned long element) const
264  {
265  return m_InternalArray[element];
266  }
267 
270  void
272  {
273  std::fill_n(begin(), size(), value);
274  } // MATCH std::array assign, ITK Fill
275 
280  /*
281  * Ask the compiler to align a type to the maximum useful alignment for the target
282  * machine you are compiling for. Whenever you leave out the alignment factor in an
283  * aligned attribute specification, the compiler automatically sets the alignment
284  * for the type to the largest alignment that is ever used for any data type on
285  * the target machine you are compiling for. Doing this can often make copy
286  * operations more efficient, because the compiler can use whatever instructions
287  * copy the biggest chunks of memory when performing copies to or from the variables
288  * that have types that you have aligned this way.
289  */
290  static_assert(VDimension > 0, "Error: Only positive value sized VDimension allowed");
291  alignas(IndexValueType) IndexValueType m_InternalArray[VDimension];
293 
295  template <typename TCoordRep>
296  inline void
298  {
299  for (unsigned int i = 0; i < VDimension; ++i)
300  {
301  m_InternalArray[i] = Math::Round<IndexValueType>(point[i]);
302  }
303  }
305 
307  template <typename TCoordRep>
308  inline void
310  {
311  for (unsigned int i = 0; i < VDimension; ++i)
312  {
313  m_InternalArray[i] = static_cast<IndexValueType>(point[i]);
314  }
315  }
317 
321  static Self
322  GetBasisIndex(unsigned int dim);
323 
324 
325  // ======================= Mirror the access pattern behavior of the std::array class
333  using const_reference = const value_type &;
334  using iterator = value_type *;
335  using const_iterator = const value_type *;
336  using size_type = unsigned int;
337  using difference_type = std::ptrdiff_t;
338  using reverse_iterator = std::reverse_iterator<iterator>;
339  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
340 
345  void
346  assign(const value_type & newValue)
347  {
348  std::fill_n(begin(), size(), newValue);
349  }
350 
351  void
352  swap(Index & other)
353  {
354  std::swap(m_InternalArray, other.m_InternalArray);
355  }
356 
357  iterator
359  {
360  return iterator(&m_InternalArray[0]);
361  }
362 
363  const_iterator
364  begin() const
365  {
366  return const_iterator(&m_InternalArray[0]);
367  }
368 
369  iterator
370  end()
371  {
372  return iterator(&m_InternalArray[VDimension]);
373  }
374 
375  const_iterator
376  end() const
377  {
378  return const_iterator(&m_InternalArray[VDimension]);
379  }
380 
381  reverse_iterator
383  {
384  return reverse_iterator(end());
385  }
386 
387  const_reverse_iterator
388  rbegin() const
389  {
390  return const_reverse_iterator(end());
391  }
392 
393  reverse_iterator
395  {
396  return reverse_iterator(begin());
397  }
398 
399  const_reverse_iterator
400  rend() const
401  {
402  return const_reverse_iterator(begin());
403  }
404 
405  constexpr size_type
406  size() const
407  {
408  return VDimension;
409  }
410 
411  constexpr size_type
412  max_size() const
413  {
414  return VDimension;
415  }
416 
417  constexpr bool
418  empty() const
419  {
420  return false;
421  }
422 
423  constexpr reference operator[](size_type pos) { return m_InternalArray[pos]; }
424 
425  constexpr const_reference operator[](size_type pos) const { return m_InternalArray[pos]; }
426 
427  reference
429  {
430  ExceptionThrowingBoundsCheck(pos);
431  return m_InternalArray[pos];
432  }
433 
434  const_reference
435  at(size_type pos) const
436  {
437  ExceptionThrowingBoundsCheck(pos);
438  return m_InternalArray[pos];
439  }
440 
441  reference
443  {
444  return *begin();
445  }
446 
447  const_reference
448  front() const
449  {
450  return *begin();
451  }
452 
453  reference
455  {
456  return VDimension ? *(end() - 1) : *end();
457  }
458 
459  const_reference
460  back() const
461  {
462  return VDimension ? *(end() - 1) : *end();
463  }
464 
467  {
468  return &m_InternalArray[0];
469  }
470 
471  const IndexValueType *
472  data() const
473  {
474  return &m_InternalArray[0];
475  }
476 
477 
480  static constexpr Self
481  Filled(const IndexValueType value)
482  {
483  Self result{};
484  for (IndexValueType & indexValue : result.m_InternalArray)
485  {
486  indexValue = value;
487  }
488  return result;
489  }
491 
492 
493 private:
494  void
496  {
497  if (pos >= VDimension)
498  {
499  throw std::out_of_range("array::ExceptionThrowingBoundsCheck");
500  }
501  }
502 
503 }; //------------ End struct Index
504 
505 template <unsigned int VDimension>
506 Index<VDimension>
508 {
509  Self ind{ { 0 } };
510 
511  ind.m_InternalArray[dim] = 1;
512  return ind;
513 }
514 
515 template <unsigned int VDimension>
516 std::ostream &
517 operator<<(std::ostream & os, const Index<VDimension> & obj)
518 {
519  os << "[";
520  for (unsigned int i = 0; i + 1 < VDimension; ++i)
521  {
522  os << obj[i] << ", ";
523  }
524  if (VDimension >= 1)
525  {
526  os << obj[VDimension - 1];
527  }
528  os << "]";
529  return os;
530 }
531 
532 // ======================= Mirror the access pattern behavior of the std::array class
533 // Array comparisons.
534 template <unsigned int VDimension>
535 inline bool
537 {
538  return std::equal(one.begin(), one.end(), two.begin());
539 }
540 
541 template <unsigned int VDimension>
542 inline bool
544 {
545  return !(one == two);
546 }
547 
548 template <unsigned int VDimension>
549 inline bool
551 {
552  return std::lexicographical_compare(one.begin(), one.end(), two.begin(), two.end());
553 }
554 
555 template <unsigned int VDimension>
556 inline bool
558 {
559  return two < one;
560 }
561 
562 template <unsigned int VDimension>
563 inline bool
565 {
566  return !(one > two);
567 }
568 
569 template <unsigned int VDimension>
570 inline bool
572 {
573  return !(one < two);
574 }
575 
576 // Specialized algorithms [6.2.2.2].
577 template <unsigned int VDimension>
578 inline void
580 {
582 }
583 
584 
586 template <typename... T>
587 auto
588 MakeIndex(const T... values)
589 {
590  const auto toValueType = [](const auto value) {
591  static_assert(std::is_integral<decltype(value)>::value, "Each value must have an integral type!");
592  return static_cast<IndexValueType>(value);
593  };
594  return Index<sizeof...(T)>{ { toValueType(values)... } };
595 }
597 
598 
599 // static constexpr definition explicitly needed in C++11
600 template <unsigned int VDimension>
601 constexpr unsigned int Index<VDimension>::Dimension;
602 } // end namespace itk
603 
604 #endif
itk::Index::operator[]
constexpr const_reference operator[](size_type pos) const
Definition: itkIndex.h:425
itk::Index< Self::ImageDimension >::const_reverse_iterator
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: itkIndex.h:339
itk::Index
Represent a n-dimensional index in a n-dimensional image.
Definition: itkIndex.h:67
itk::operator<
bool operator<(const Index< VDimension > &one, const Index< VDimension > &two)
Definition: itkIndex.h:550
itk::operator<=
bool operator<=(const Index< VDimension > &one, const Index< VDimension > &two)
Definition: itkIndex.h:564
itk::Index::max_size
constexpr size_type max_size() const
Definition: itkIndex.h:412
itk::Size
Represent a n-dimensional size (bounds) of a n-dimensional image.
Definition: itkSize.h:69
itk::operator<<
std::ostream & operator<<(std::ostream &os, const Array< TValue > &arr)
Definition: itkArray.h:216
itkOffset.h
itk::Index::assign
void assign(const value_type &newValue)
Definition: itkIndex.h:346
itk::Index< Self::ImageDimension >::reference
value_type & reference
Definition: itkIndex.h:332
itk::Index::CopyWithRound
void CopyWithRound(const FixedArray< TCoordRep, VDimension > &point)
Definition: itkIndex.h:297
itk::swap
void swap(Array< T > &a, Array< T > &b)
Definition: itkArray.h:242
itk::Index< Self::ImageDimension >::IndexValueType
::itk::IndexValueType IndexValueType
Definition: itkIndex.h:78
itk::Index::at
const_reference at(size_type pos) const
Definition: itkIndex.h:435
itk::Index::SetIndex
void SetIndex(const IndexValueType val[VDimension])
Definition: itkIndex.h:239
itk::Index::operator+=
const Self & operator+=(const OffsetType &offset)
Definition: itkIndex.h:164
itk::Index::operator*
const Self operator*(const SizeType &vec) const
Definition: itkIndex.h:215
itk::Index::Dimension
static constexpr unsigned int Dimension
Definition: itkIndex.h:88
itk::swap
void swap(Index< VDimension > &one, Index< VDimension > &two)
Definition: itkIndex.h:579
itk::Index::operator-
const Self operator-(const OffsetType &off) const
Definition: itkIndex.h:188
itk::Index::SetElement
void SetElement(unsigned long element, IndexValueType val)
Definition: itkIndex.h:251
itk::Index::operator+
const Self operator+(const SizeType &sz) const
Definition: itkIndex.h:100
itk::Index::Fill
void Fill(IndexValueType value)
Definition: itkIndex.h:271
itk::Index::front
const_reference front() const
Definition: itkIndex.h:448
itk::Index::end
iterator end()
Definition: itkIndex.h:370
itk::Index::back
const_reference back() const
Definition: itkIndex.h:460
itk::Index::operator+
const Self operator+(const OffsetType &offset) const
Definition: itkIndex.h:151
itk::Index::begin
iterator begin()
Definition: itkIndex.h:358
itk::Index< Self::ImageDimension >::difference_type
std::ptrdiff_t difference_type
Definition: itkIndex.h:337
itk::Index::front
reference front()
Definition: itkIndex.h:442
itk::Index::begin
const_iterator begin() const
Definition: itkIndex.h:364
itk::Index::GetIndex
const IndexValueType * GetIndex() const
Definition: itkIndex.h:229
itk::Index::rend
const_reverse_iterator rend() const
Definition: itkIndex.h:400
itk::Index< Self::ImageDimension >::OffsetValueType
::itk::OffsetValueType OffsetValueType
Definition: itkIndex.h:85
itk::Index::at
reference at(size_type pos)
Definition: itkIndex.h:428
itk::Index::size
constexpr size_type size() const
Definition: itkIndex.h:406
itk::Index::operator-
const OffsetType operator-(const Self &vec) const
Definition: itkIndex.h:201
itk::Index< Self::ImageDimension >::const_reference
const value_type & const_reference
Definition: itkIndex.h:333
itk::Index::back
reference back()
Definition: itkIndex.h:454
itk::Index::m_InternalArray
IndexValueType m_InternalArray[VDimension]
Definition: itkIndex.h:290
itk::operator>=
bool operator>=(const Index< VDimension > &one, const Index< VDimension > &two)
Definition: itkIndex.h:571
itk::Offset::m_InternalArray
OffsetValueType m_InternalArray[VDimension]
Definition: itkOffset.h:243
itk::Index::rbegin
const_reverse_iterator rbegin() const
Definition: itkIndex.h:388
itk::operator>
bool operator>(const Index< VDimension > &one, const Index< VDimension > &two)
Definition: itkIndex.h:557
itk::Index::empty
constexpr bool empty() const
Definition: itkIndex.h:418
itk::operator==
bool operator==(const Index< VDimension > &one, const Index< VDimension > &two)
Definition: itkIndex.h:536
itk::FixedArray
Simulate a standard C array with copy semantics.
Definition: itkFixedArray.h:52
itk::Index::CopyWithCast
void CopyWithCast(const FixedArray< TCoordRep, VDimension > &point)
Definition: itkIndex.h:309
itk::Index::GetIndexDimension
static constexpr unsigned int GetIndexDimension()
Definition: itkIndex.h:92
itk::Index< Self::ImageDimension >::iterator
value_type * iterator
Definition: itkIndex.h:334
itk::Index::Filled
static constexpr Self Filled(const IndexValueType value)
Definition: itkIndex.h:481
itk::Index::GetElement
IndexValueType GetElement(unsigned long element) const
Definition: itkIndex.h:263
itk::Offset
Represent a n-dimensional offset between two n-dimensional indexes of n-dimensional image.
Definition: itkOffset.h:67
itk::Index::rbegin
reverse_iterator rbegin()
Definition: itkIndex.h:382
itk::Index::end
const_iterator end() const
Definition: itkIndex.h:376
itk::operator!=
bool operator!=(const Index< VDimension > &one, const Index< VDimension > &two)
Definition: itkIndex.h:543
itk::MakeIndex
auto MakeIndex(const T... values)
Definition: itkIndex.h:588
itk::Index::rend
reverse_iterator rend()
Definition: itkIndex.h:394
itk::Size::m_InternalArray
SizeValueType m_InternalArray[VDimension]
Definition: itkSize.h:230
itk
The "itk" namespace contains all Insight Segmentation and Registration Toolkit (ITK) classes....
Definition: itkAnnulusOperator.h:24
itk::Index::data
const IndexValueType * data() const
Definition: itkIndex.h:472
itk::OffsetValueType
signed long OffsetValueType
Definition: itkIntTypes.h:94
itk::Index< Self::ImageDimension >::size_type
unsigned int size_type
Definition: itkIndex.h:336
itk::IndexValueType
signed long IndexValueType
Definition: itkIntTypes.h:90
itk::Index::GetBasisIndex
static Self GetBasisIndex(unsigned int dim)
Definition: itkIndex.h:507
itk::Index< Self::ImageDimension >::value_type
::itk::IndexValueType value_type
Definition: itkIndex.h:331
itk::Index::operator+=
const Self & operator+=(const SizeType &sz)
Definition: itkIndex.h:113
itk::Index::operator-
const Self operator-(const SizeType &sz) const
Definition: itkIndex.h:126
itk::Index< Self::ImageDimension >::const_iterator
const value_type * const_iterator
Definition: itkIndex.h:335
itk::Index< Self::ImageDimension >::reverse_iterator
std::reverse_iterator< iterator > reverse_iterator
Definition: itkIndex.h:338
itk::GTest::TypedefsAndConstructors::Dimension2::Dimension
constexpr unsigned int Dimension
Definition: itkGTestTypedefsAndConstructors.h:44
itk::Index::operator[]
constexpr reference operator[](size_type pos)
Definition: itkIndex.h:423
itk::Index::ExceptionThrowingBoundsCheck
void ExceptionThrowingBoundsCheck(size_type pos) const
Definition: itkIndex.h:495
itk::Index::swap
void swap(Index &other)
Definition: itkIndex.h:352
itk::Index::operator-=
const Self & operator-=(const SizeType &sz)
Definition: itkIndex.h:139
itk::Index::data
IndexValueType * data()
Definition: itkIndex.h:466
itk::Index::operator-=
const Self & operator-=(const OffsetType &offset)
Definition: itkIndex.h:176