| 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 |
|
|