ITK  6.0.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 * 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#ifndef itkIndex_h
19#define itkIndex_h
20
21#include "itkMakeFilled.h"
22#include "itkOffset.h"
23
24#include <cstddef> // For ptrdiff_t.
25#include <type_traits> // For is_integral.
26
27namespace itk
28{
29
67template <unsigned int VDimension = 2>
68struct ITK_TEMPLATE_EXPORT Index final
69{
70public:
71 // Using the `rule of zero` to this aggregate type
72 // C++20 changes the definition of aggregate such that classes with any user-declared ctors are no longer aggregates.
73
75 using Self = Index;
76
80
83
87
89 static constexpr unsigned int Dimension = VDimension;
90
92 static constexpr unsigned int
94 {
95 return VDimension;
96 }
97
98
100 const Self
101 operator+(const SizeType & sz) const
102 {
103 Self result;
104
105 for (unsigned int i = 0; i < VDimension; ++i)
106 {
107 result[i] = m_InternalArray[i] + static_cast<IndexValueType>(sz[i]);
108 }
109 return result;
110 }
111
113 const Self &
115 {
116 for (unsigned int i = 0; i < VDimension; ++i)
117 {
118 m_InternalArray[i] += static_cast<IndexValueType>(sz[i]);
119 }
120 return *this;
121 }
126 const Self
127 operator-(const SizeType & sz) const
128 {
129 Self result;
130
131 for (unsigned int i = 0; i < VDimension; ++i)
132 {
133 result[i] = m_InternalArray[i] - static_cast<IndexValueType>(sz[i]);
134 }
135 return result;
136 }
137
139 const Self &
141 {
142 for (unsigned int i = 0; i < VDimension; ++i)
143 {
144 m_InternalArray[i] -= static_cast<IndexValueType>(sz[i]);
145 }
146 return *this;
147 }
151 const Self
152 operator+(const OffsetType & offset) const
153 {
154 Self result;
155
156 for (unsigned int i = 0; i < VDimension; ++i)
157 {
158 result[i] = m_InternalArray[i] + offset[i];
159 }
160 return result;
161 }
162
164 const Self &
165 operator+=(const OffsetType & offset)
166 {
167 for (unsigned int i = 0; i < VDimension; ++i)
168 {
169 m_InternalArray[i] += offset[i];
170 }
171 return *this;
172 }
176 const Self &
177 operator-=(const OffsetType & offset)
178 {
179 for (unsigned int i = 0; i < VDimension; ++i)
180 {
181 m_InternalArray[i] -= offset[i];
182 }
183 return *this;
184 }
188 const Self
189 operator-(const OffsetType & off) const
190 {
191 Self result;
192
193 for (unsigned int i = 0; i < VDimension; ++i)
194 {
195 result[i] = m_InternalArray[i] - off.m_InternalArray[i];
196 }
197 return result;
198 }
199
201 const OffsetType
202 operator-(const Self & vec) const
203 {
204 OffsetType result;
205
206 for (unsigned int i = 0; i < VDimension; ++i)
207 {
208 result[i] = m_InternalArray[i] - vec.m_InternalArray[i];
209 }
210 return result;
211 }
212
216 const Self
217 operator*(const SizeType & vec) const
218 {
219 Self result;
220
221 for (unsigned int i = 0; i < VDimension; ++i)
222 {
223 result[i] = m_InternalArray[i] * static_cast<IndexValueType>(vec.m_InternalArray[i]);
224 }
225 return result;
226 }
227
230 const IndexValueType *
231 GetIndex() const
232 {
233 return m_InternalArray;
234 }
235
240 void
241 SetIndex(const IndexValueType val[VDimension])
242 {
243 std::copy_n(val, VDimension, m_InternalArray);
244 }
245
252 void
253 SetElement(unsigned int element, IndexValueType val)
254 {
255 m_InternalArray[element] = val;
256 }
257
265 GetElement(unsigned int element) const
266 {
267 return m_InternalArray[element];
268 }
269
272 void
274 {
275 std::fill_n(begin(), size(), value);
276 } // MATCH std::array assign, ITK Fill
277
282 /*
283 * Ask the compiler to align a type to the maximum useful alignment for the target
284 * machine you are compiling for. Whenever you leave out the alignment factor in an
285 * aligned attribute specification, the compiler automatically sets the alignment
286 * for the type to the largest alignment that is ever used for any data type on
287 * the target machine you are compiling for. Doing this can often make copy
288 * operations more efficient, because the compiler can use whatever instructions
289 * copy the biggest chunks of memory when performing copies to or from the variables
290 * that have types that you have aligned this way.
291 */
292 static_assert(VDimension > 0, "Error: Only positive value sized VDimension allowed");
293 alignas(IndexValueType) IndexValueType m_InternalArray[VDimension];
297 template <typename TCoordinate>
298 inline void
300 {
301 for (unsigned int i = 0; i < VDimension; ++i)
302 {
303 m_InternalArray[i] = Math::Round<IndexValueType>(point[i]);
304 }
305 }
309 template <typename TCoordinate>
310 inline void
312 {
313 for (unsigned int i = 0; i < VDimension; ++i)
314 {
315 m_InternalArray[i] = static_cast<IndexValueType>(point[i]);
316 }
317 }
323 static Self
324 GetBasisIndex(unsigned int dim);
325
326
327 // ======================= Mirror the access pattern behavior of the std::array class
337 using const_iterator = const value_type *;
338 using size_type = unsigned int;
339 using difference_type = ptrdiff_t;
340 using reverse_iterator = std::reverse_iterator<iterator>;
341 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
342
347 void
348 assign(const value_type & newValue)
349 {
350 std::fill_n(begin(), size(), newValue);
351 }
352
353 void
354 swap(Index & other) noexcept
355 {
356 std::swap(m_InternalArray, other.m_InternalArray);
357 }
358
359 constexpr const_iterator
360 cbegin() const
361 {
362 return &m_InternalArray[0];
363 }
364
365 constexpr iterator
367 {
368 return &m_InternalArray[0];
369 }
370
371 constexpr const_iterator
372 begin() const
373 {
374 return &m_InternalArray[0];
375 }
376
377 constexpr const_iterator
378 cend() const
379 {
380 return &m_InternalArray[VDimension];
381 }
382
383 constexpr iterator
385 {
386 return &m_InternalArray[VDimension];
387 }
388
389 constexpr const_iterator
390 end() const
391 {
392 return &m_InternalArray[VDimension];
393 }
394
395 reverse_iterator
397 {
398 return reverse_iterator(end());
399 }
400
401 const_reverse_iterator
402 rbegin() const
403 {
404 return const_reverse_iterator(end());
405 }
406
407 reverse_iterator
409 {
410 return reverse_iterator(begin());
411 }
412
413 const_reverse_iterator
414 rend() const
415 {
416 return const_reverse_iterator(begin());
417 }
418
419 constexpr size_type
420 size() const
421 {
422 return VDimension;
423 }
424
425 constexpr size_type
426 max_size() const
427 {
428 return VDimension;
429 }
430
431 constexpr bool
432 empty() const
433 {
434 return false;
435 }
436
437 constexpr reference
439 {
440 return m_InternalArray[pos];
441 }
442
443 constexpr const_reference
445 {
446 return m_InternalArray[pos];
447 }
448
449 reference
451 {
452 ExceptionThrowingBoundsCheck(pos);
453 return m_InternalArray[pos];
454 }
455
456 const_reference
457 at(size_type pos) const
458 {
459 ExceptionThrowingBoundsCheck(pos);
460 return m_InternalArray[pos];
461 }
462
463 constexpr reference
465 {
466 return *begin();
467 }
468
469 constexpr const_reference
470 front() const
471 {
472 return *begin();
473 }
474
475 constexpr reference
477 {
478 return VDimension ? *(end() - 1) : *end();
479 }
480
481 constexpr const_reference
482 back() const
483 {
484 return VDimension ? *(end() - 1) : *end();
485 }
486
489 {
490 return &m_InternalArray[0];
491 }
492
493 const IndexValueType *
494 data() const
495 {
496 return &m_InternalArray[0];
497 }
498
499
502 static constexpr Self
504 {
505 return MakeFilled<Self>(value);
506 }
507
508
509private:
510 void
512 {
513 if (pos >= VDimension)
514 {
515 throw std::out_of_range("array::ExceptionThrowingBoundsCheck");
516 }
517 }
518
519}; //------------ End struct Index
520
521template <unsigned int VDimension>
522Index<VDimension>
524{
525 Self ind{ { 0 } };
526
527 ind.m_InternalArray[dim] = 1;
528 return ind;
529}
530
531template <unsigned int VDimension>
532std::ostream &
533operator<<(std::ostream & os, const Index<VDimension> & obj)
534{
535 os << '[';
536 for (unsigned int i = 0; i + 1 < VDimension; ++i)
537 {
538 os << obj[i] << ", ";
539 }
540 if constexpr (VDimension >= 1)
541 {
542 os << obj[VDimension - 1];
543 }
544 os << ']';
545 return os;
546}
547
548// ======================= Mirror the access pattern behavior of the std::array class
549// Array comparisons.
550template <unsigned int VDimension>
551inline bool
553{
554 return std::equal(one.begin(), one.end(), two.begin());
555}
556
557template <unsigned int VDimension>
558inline bool
560{
561 return !(one == two);
562}
563
564template <unsigned int VDimension>
565inline bool
566operator<(const Index<VDimension> & one, const Index<VDimension> & two)
567{
568 return std::lexicographical_compare(one.begin(), one.end(), two.begin(), two.end());
569}
570
571template <unsigned int VDimension>
572inline bool
574{
575 return two < one;
576}
577
578template <unsigned int VDimension>
579inline bool
580operator<=(const Index<VDimension> & one, const Index<VDimension> & two)
581{
582 return !(one > two);
583}
584
585template <unsigned int VDimension>
586inline bool
588{
589 return !(one < two);
590}
591
592// Specialized algorithms [6.2.2.2].
593template <unsigned int VDimension>
594inline void
596{
597 std::swap(one.m_InternalArray, two.m_InternalArray);
598}
599
600
602template <typename... T>
603auto
604MakeIndex(const T... values)
605{
606 const auto toValueType = [](const auto value) {
607 static_assert(std::is_integral_v<decltype(value)>, "Each value must have an integral type!");
608 return static_cast<IndexValueType>(value);
609 };
610 return Index<sizeof...(T)>{ { toValueType(values)... } };
611}
614} // end namespace itk
615
616#endif
Pixel-wise addition of two images.
Simulate a standard C array with copy semantics.
Definition: itkFixedArray.h:54
The "itk" namespace contains all Insight Segmentation and Registration Toolkit (ITK) classes....
void swap(Index< VDimension > &one, Index< VDimension > &two) noexcept
Definition: itkIndex.h:595
auto MakeIndex(const T... values)
Definition: itkIndex.h:604
*par Constraints *The filter image with at least two dimensions and a vector *length of at least The theory supports extension to scalar but *the implementation of the itk vector classes do not **The template parameter TRealType must be floating point(float or double) or *a user-defined "real" numerical type with arithmetic operations defined *sufficient to compute derivatives. **\par Performance *This filter will automatically multithread if run with *SetUsePrincipleComponents
bool operator>(const Index< VDimension > &one, const Index< VDimension > &two)
Definition: itkIndex.h:573
bool operator<=(const Index< VDimension > &one, const Index< VDimension > &two)
Definition: itkIndex.h:580
long IndexValueType
Definition: itkIntTypes.h:93
bool operator==(const Index< VDimension > &one, const Index< VDimension > &two)
Definition: itkIndex.h:552
std::ostream & operator<<(std::ostream &os, const Index< VDimension > &obj)
Definition: itkIndex.h:533
bool operator!=(const Index< VDimension > &one, const Index< VDimension > &two)
Definition: itkIndex.h:559
bool operator<(const Index< VDimension > &one, const Index< VDimension > &two)
Definition: itkIndex.h:566
bool operator>=(const Index< VDimension > &one, const Index< VDimension > &two)
Definition: itkIndex.h:587
long OffsetValueType
Definition: itkIntTypes.h:97
Represent a n-dimensional index in a n-dimensional image.
Definition: itkIndex.h:69
constexpr const_reference operator[](size_type pos) const
Definition: itkIndex.h:444
const Self operator*(const SizeType &vec) const
Definition: itkIndex.h:217
const OffsetType operator-(const Self &vec) const
Definition: itkIndex.h:202
const Self & operator+=(const OffsetType &offset)
Definition: itkIndex.h:165
const value_type * const_iterator
Definition: itkIndex.h:337
constexpr reference front()
Definition: itkIndex.h:464
const Self & operator-=(const SizeType &sz)
Definition: itkIndex.h:140
const_reverse_iterator rbegin() const
Definition: itkIndex.h:402
static constexpr Self Filled(const IndexValueType value)
Definition: itkIndex.h:503
reverse_iterator rend()
Definition: itkIndex.h:408
void assign(const value_type &newValue)
Definition: itkIndex.h:348
value_type * iterator
Definition: itkIndex.h:336
constexpr size_type max_size() const
Definition: itkIndex.h:426
reverse_iterator rbegin()
Definition: itkIndex.h:396
const_reverse_iterator rend() const
Definition: itkIndex.h:414
void ExceptionThrowingBoundsCheck(size_type pos) const
Definition: itkIndex.h:511
IndexValueType m_InternalArray[VDimension]
Definition: itkIndex.h:292
constexpr bool empty() const
Definition: itkIndex.h:432
constexpr size_type size() const
Definition: itkIndex.h:420
const IndexValueType * GetIndex() const
Definition: itkIndex.h:231
constexpr const_iterator begin() const
Definition: itkIndex.h:372
const Self operator-(const OffsetType &off) const
Definition: itkIndex.h:189
static Self GetBasisIndex(unsigned int dim)
Definition: itkIndex.h:523
unsigned int size_type
Definition: itkIndex.h:338
itk::IndexValueType IndexValueType
Definition: itkIndex.h:79
reference at(size_type pos)
Definition: itkIndex.h:450
const Self operator+(const SizeType &sz) const
Definition: itkIndex.h:101
std::reverse_iterator< iterator > reverse_iterator
Definition: itkIndex.h:340
itk::IndexValueType value_type
Definition: itkIndex.h:333
const value_type & const_reference
Definition: itkIndex.h:335
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: itkIndex.h:341
constexpr reference operator[](size_type pos)
Definition: itkIndex.h:438
constexpr const_iterator end() const
Definition: itkIndex.h:390
constexpr reference back()
Definition: itkIndex.h:476
constexpr iterator end()
Definition: itkIndex.h:384
const Self operator-(const SizeType &sz) const
Definition: itkIndex.h:127
void Fill(IndexValueType value)
Definition: itkIndex.h:273
void CopyWithCast(const FixedArray< TCoordinate, VDimension > &point)
Definition: itkIndex.h:311
void CopyWithRound(const FixedArray< TCoordinate, VDimension > &point)
Definition: itkIndex.h:299
constexpr const_reference back() const
Definition: itkIndex.h:482
const IndexValueType * data() const
Definition: itkIndex.h:494
void SetElement(unsigned int element, IndexValueType val)
Definition: itkIndex.h:253
const Self & operator+=(const SizeType &sz)
Definition: itkIndex.h:114
constexpr iterator begin()
Definition: itkIndex.h:366
value_type & reference
Definition: itkIndex.h:334
IndexValueType * data()
Definition: itkIndex.h:488
const Self operator+(const OffsetType &offset) const
Definition: itkIndex.h:152
IndexValueType GetElement(unsigned int element) const
Definition: itkIndex.h:265
ptrdiff_t difference_type
Definition: itkIndex.h:339
constexpr const_iterator cend() const
Definition: itkIndex.h:378
constexpr const_reference front() const
Definition: itkIndex.h:470
itk::OffsetValueType OffsetValueType
Definition: itkIndex.h:86
constexpr const_iterator cbegin() const
Definition: itkIndex.h:360
static constexpr unsigned int GetIndexDimension()
Definition: itkIndex.h:93
void swap(Index &other) noexcept
Definition: itkIndex.h:354
void SetIndex(const IndexValueType val[VDimension])
Definition: itkIndex.h:241
const Self & operator-=(const OffsetType &offset)
Definition: itkIndex.h:177
const_reference at(size_type pos) const
Definition: itkIndex.h:457
OffsetValueType m_InternalArray[VDimension]
Definition: itkOffset.h:242
SizeValueType m_InternalArray[VDimension]
Definition: itkSize.h:244