KWStyle - itkIndex.h
 
Matrix View
Description

1 /*=========================================================================
2
3   Program:   Insight Segmentation & Registration Toolkit
4   Module:    $RCSfile: itkIndex.h.html,v $
5   Language:  C++
6   Date:      $Date: 2006/01/17 19:15:40 $
7   Version:   $Revision: 1.4 $
8
9   Copyright (c) Insight Software Consortium. All rights reserved.
10   See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
11
12      This software is distributed WITHOUT ANY WARRANTY; without even 
13      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
14      PURPOSE.  See the above copyright notices for more information.
15
16 =========================================================================*/
17 #ifndef __itkIndex_h
18 #define __itkIndex_h
19
20 #include "itkMacro.h"
21 #include "itkOffset.h"
22 #include "itkSize.h"
23
24 #include <memory>
25
26 #include "itkExceptionObject.h"
27
28 namespace itk
29 {
30
31 namespace Functor
32 {
33 template<unsigned int VIndexDimension> class IndexLexicographicCompare;
34 }
35
36 /** \class Index
37  * \brief Represent a n-dimensional index in a n-dimensional image.
38  *
39  * Index is a templated class to represent a multi-dimensional index,
40  * i.e. (i,j,k,...). Index is templated over the dimension of the index.  
41  * ITK assumes the first element of an index is the fastest moving index.
42  *
43  * For efficiency sake, Index does not define a default constructor, a
44  * copy constructor, or an operator=. We rely on the compiler to provide
45  * efficient bitwise copies.
46  *
47  * Index is an "aggregate" class.  Its data is public (m_Index)
48  * allowing for fast and convenient instantiations/assignments.
49  *
50  * The following syntax for assigning an index is allowed/suggested:
51  *
52  *    Index<3> index = {{5, 2, 7}};
53  *
54  * The double braces {{ and }} are needed to prevent a compiler warning
55  * about a partly bracketed initializer.
56  *
57  * \remark
58  * Should there be an itkBoundedIndex to handle bounds checking? Or should
59  * there be an API to perform bounded increments in the iterator. 
60  *
61  * \ingroup ImageAccess
62  * \ingroup ImageObjects
63  */
64
65 template<unsigned int VIndexDimension=2>
66 class Index {
67 public:
68   /** Standard class typedefs. */
69   typedef Index  Self;
70
71   /** Compatible Index and value typedef */
72   typedef   Index<VIndexDimension>  IndexType;
73 TDA   typedef   long  IndexValueType;
74     
75   /** Get the dimension (size) of the index. */
76   static unsigned int GetIndexDimension() { return VIndexDimension; }
77
78   /** Compatible Size typedef. */
79   typedef   Size<VIndexDimension>  SizeType;
80
81   /** Compatible Offset and Offset value typedef. */
82   typedef   Offset<VIndexDimension>  OffsetType;
83 TDA   typedef   typename OffsetType::OffsetValueType OffsetValueType;
84
85   /** Lexicographic ordering functor type.  */
86 LEN   typedef Functor::IndexLexicographicCompare<VIndexDimension> LexicographicCompare;
87
88   /** Add a size to an index. This method models a random access Index. */
89   const Self
90   operator+(const SizeType &size) const
91     {
92     Self result;
93     for (unsigned int i=0; i < VIndexDimension; i++)
94       { result[i] = m_Index[i] + static_cast<IndexValueType>(size[i]); }
95     return result;
96     }
97
98   /** Increment index by a size. This method models a random access Index. */
99   const Self &
100   operator+=(const SizeType &size)
101     {
102     for (unsigned int i=0; i < VIndexDimension; i++)
103       { m_Index[i] += static_cast<IndexValueType>(size[i]); }
104     return *this;
105     }
106
107 LEN   /** Subtract a size from an index. This method models a random access Index. */
108   const Self
109   operator-(const SizeType &size) const
110     {
111     Self result;
112     for (unsigned int i=0; i < VIndexDimension; i++)
113       { result[i] = m_Index[i] - static_cast<IndexValueType>(size[i]); }
114     return result;
115     }
116
117   /** Decrement index by a size. This method models a random access Index. */
118   const Self &
119   operator-=(const SizeType &size)
120     {
121     for (unsigned int i=0; i < VIndexDimension; i++)
122       { m_Index[i] -= static_cast<IndexValueType>(size[i]); }
123     return *this;
124     }
125
126   /** Add an offset to an index. */
127   const Self
128   operator+(const OffsetType &offset) const
129     {
130     Self result;
131     for (unsigned int i=0; i < VIndexDimension; i++)
132       { result[i] = m_Index[i] + offset[i]; }
133     return result;
134     }
135
136   /** Increment index by an offset. This method models a random access Index. */
137   const Self &
138   operator+=(const OffsetType &offset)
139     {
140     for (unsigned int i=0; i < VIndexDimension; i++)
141       { m_Index[i] += offset[i]; }
142     return *this;
143     }
144
145   /** Decrement index by an offset. This method models a random access Index. */
146   const Self &
147   operator-=(const OffsetType &offset)
148     {
149     for (unsigned int i=0; i < VIndexDimension; i++)
150       { m_Index[i] -= offset[i]; }
151     return *this;
152     }
153
154   /** Subtract an offset from an index. */
155   const Self
156   operator-(const OffsetType &off) const
157     {
158     Self result;
159     for (unsigned int i=0; i < VIndexDimension; i++)
160       { result[i] = m_Index[i] - off.m_Offset[i]; }
161     return result;
162     }
163
164   /** Subtract two indices. This method models a random access Index. */
165   const OffsetType
166   operator-(const Self &vec) const
167     {
168     OffsetType result;
169     for (unsigned int i=0; i < VIndexDimension; i++)
170       { result[i] = m_Index[i] - vec.m_Index[i]; }
171     return result;
172     }
173
174   /** Multiply an index by a size (elementwise product). This method 
175    * models a random access Index.  */
176   const Self
177   operator*(const SizeType &vec) const
178     {
179     Self result;
180     for (unsigned int i=0; i < VIndexDimension; i++)
181       { result[i] = m_Index[i] * static_cast<IndexValueType>(vec.m_Size[i]); }
182     return result;
183     }
184
185   /** Compare two indices. */
186   bool
187   operator==(const Self &vec) const
188     {
189     bool same=true;
190     for (unsigned int i=0; i < VIndexDimension && same; i++)
191       { same = (m_Index[i] == vec.m_Index[i]); }
192     return same;
193     }
194
195   /** Compare two indices. */
196   bool
197   operator!=(const Self &vec) const
198     {
199     bool same=true;
200     for (unsigned int i=0; i < VIndexDimension && same; i++)
201       { same = (m_Index[i] == vec.m_Index[i]); }
202     return !same;
203     }
204
205   /** Access an element of the index. Elements are numbered
206    * 0, ..., VIndexDimension-1. No bounds checking is performed. */
207   IndexValueType & operator[](unsigned int dim)
208     { return m_Index[dim]; }
209
210   /** Access an element of the index. Elements are numbered
211    * 0, ..., VIndexDimension-1. This version can only be an rvalue.
212    * No bounds checking is performed. */
213   IndexValueType operator[](unsigned int dim) const
214     { return m_Index[dim]; }
215
216   /** Get the index. This provides a read only reference to the index.
217    * \sa SetIndex() */
218   const IndexValueType *GetIndex() const { return m_Index; };
219
220   /** Set the index.
221    * Try to prototype this function so that val has to point to a block of
222    * memory that is the appropriate size.
223    * \sa GetIndex() */
224   void SetIndex(const IndexValueType val[VIndexDimension])
225     { memcpy(m_Index, val, sizeof(IndexValueType)*VIndexDimension); }
226
227   /** Sets the value of one of the elements in the index.
228    * This method is mainly intended to facilitate the access to elements
229    * from Tcl and Python where C++ notation is not very convenient.
230    * \warning No bound checking is performed
231    * \sa SetIndex()
232    * \sa GetElement() */
233   void SetElement(unsigned long element, IndexValueType val )
234     { m_Index[ element ] = val;  }
235
236   /** Gets the value of one of the elements in the index.
237    * This method is mainly intended to facilitate the access to elements
238    * from Tcl and Python where C++ notation is not very convenient.
239    * \warning No bound checking is performed
240    * \sa GetIndex()
241    * \sa SetElement() */
242   IndexValueType GetElement( unsigned long element )
243     { return m_Index[ element ]; }
244
245   /** Return a basis vector of the form [0, ..., 0, 1, 0, ... 0] where the "1"
246    * is positioned in the location specified by the parameter "dim". Valid
247    * values of "dim" are 0, ..., VIndexDimension-1. */
248   static Self GetBasisIndex(unsigned int dim); 
249
250   /** Set one value for the index in all dimensions.  Useful for initializing
251    * an offset to zero. */
252   void Fill(IndexValueType value)
253     { for(unsigned int i=0;i < VIndexDimension; ++i) m_Index[i] = value; }
254
255   /** Index is an "aggregate" class.  Its data is public (m_Index)
256    * allowing for fast and convienent instantiations/assignments.
257    *
258    * The following syntax for assigning an index is allowed/suggested:
259    *    Index<3> index = {5, 2, 7}; */
260   IndexValueType m_Index[VIndexDimension];
261   
262 };
263
264 namespace Functor
265 {
266 /** \class IndexLexicographicCompare
267  * \brief Order Index instances lexicographically.
268  *
269  * This is a comparison functor suitable for storing Index instances
270  * in an STL container.  The ordering is total and unique but has
271  * little geometric meaning.
272  */
273 template<unsigned int VIndexDimension>
274 class IndexLexicographicCompare
275 {
276 public:
277   bool operator()(Index<VIndexDimension> const& l,
278                   Index<VIndexDimension> const& r) const
279     {
280     for(unsigned int i=0; i < VIndexDimension; ++i)
281       {
282       if(l.m_Index[i] < r.m_Index[i])
283         {
284         return true;
285         }
286       else if(l.m_Index[i] > r.m_Index[i])
287         {
288         return false;
289         }
290       }
291     return false;
292     }
293 };
294 }
295
296 template<unsigned int VIndexDimension>
297 Index<VIndexDimension> 
298 Index<VIndexDimension>
299 ::GetBasisIndex(unsigned int dim)
300 {
301   Self ind;
302   
303   memset(ind.m_Index, 0, sizeof(IndexValueType)*VIndexDimension);
304   ind.m_Index[dim] = 1;
305   return ind;
306 }
307
308 template<unsigned int VIndexDimension>
309 std::ostream & operator<<(std::ostream &os, const Index<VIndexDimension> &ind)
310 {
311   os << "[";
312   for (unsigned int i=0; i+1 < VIndexDimension; ++i)
313     {
314     os << ind[i] << ", ";
315     }
316   if (VIndexDimension >= 1)
317     {
318     os << ind[VIndexDimension-1];
319     }
320   os << "]";
321   return os;
322 }
323
324 #ifdef ITK_EXPLICIT_INSTANTIATION
325    extern template class Index<1>;
326 IND ***extern template class Index<2>;
327 IND ***extern template class Index<3>;
328 IND ***extern template class Index<4>;
329 IND ***extern template class Index<5>;
330 LEN,IND ***extern template std::ostream & operator<<(std::ostream &os, const Index<1> &ind);
331 LEN,IND ***extern template std::ostream & operator<<(std::ostream &os, const Index<2> &ind);
332 LEN,IND ***extern template std::ostream & operator<<(std::ostream &os, const Index<3> &ind);
333 LEN,IND ***extern template std::ostream & operator<<(std::ostream &os, const Index<4> &ind);
334 LEN,IND ***extern template std::ostream & operator<<(std::ostream &os, const Index<5> &ind);
335 #endif
336
337
338 // end namespace itk
339
340 #endif 
341

Generated by KWStyle 1.0b on Tuesday January,17 at 02:14:17PM
© Kitware Inc.