| 1 |
|
/*========================================================================= |
| 2 |
|
|
| 3 |
|
Program: Insight Segmentation & Registration Toolkit |
| 4 |
|
Module: $RCSfile: itkOffset.h.html,v $ |
| 5 |
|
Language: C++ |
| 6 |
|
Date: $Date: 2006/01/17 19:15:43 $ |
| 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 __itkOffset_h |
| 18 |
|
#define __itkOffset_h |
| 19 |
|
|
| 20 |
|
#include "itkMacro.h" |
| 21 |
|
#include "itkSize.h" |
| 22 |
|
|
| 23 |
|
#include <memory> |
| 24 |
|
|
| 25 |
|
#include "itkExceptionObject.h" |
| 26 |
|
|
| 27 |
|
namespace itk |
| 28 |
|
{ |
| 29 |
|
|
| 30 |
|
/** |
| 31 |
|
* \class Offset |
| 32 |
|
* \brief Represent the offset between two n-dimensional indexes |
| 33 |
|
* in a n-dimensional image. |
| 34 |
|
* |
| 35 |
|
* Offset is a templated class to represent a multi-dimensional offset, |
| 36 |
|
* i.e. (i,j,k,...). Offset is templated over the dimension of the space. |
| 37 |
|
* |
| 38 |
|
* For the sake of efficiency, Offset does not define a default constructor, a |
| 39 |
|
* copy constructor, or an operator=. We rely on the compiler to provide |
| 40 |
|
* efficient bitwise copies. |
| 41 |
|
* |
| 42 |
|
* \sa Index |
| 43 |
|
* \ingroup ImageAccess |
| 44 |
|
*/ |
| 45 |
|
|
| 46 |
|
|
| 47 |
|
template<unsigned int VOffsetDimension=2> |
| 48 |
|
class Offset { |
| 49 |
|
public: |
| 50 |
|
/** Standard class typedefs. */ |
| 51 |
|
typedef Offset Self; |
| 52 |
|
|
| 53 |
|
/** Get the dimension (size) of the index. */ |
| 54 |
|
static unsigned int GetOffsetDimension() { return VOffsetDimension; } |
| 55 |
|
|
| 56 |
|
/** Compatible offset typedefs. */ |
| 57 |
|
typedef Offset<VOffsetDimension> OffsetType; |
| 58 |
TDA |
typedef long OffsetValueType; |
| 59 |
|
|
| 60 |
|
/** Add an offset to an offset. */ |
| 61 |
|
const Self |
| 62 |
|
operator+(const Self &offset) const |
| 63 |
|
{ |
| 64 |
|
Self result; |
| 65 |
|
for (unsigned int i=0; i < VOffsetDimension; i++) |
| 66 |
|
{ result[i] = m_Offset[i] + offset[i]; } |
| 67 |
|
return result; |
| 68 |
|
} |
| 69 |
|
|
| 70 |
|
/** Add a size to an offset. */ |
| 71 |
|
const Self |
| 72 |
|
operator+(const Size<VOffsetDimension> &size) const |
| 73 |
|
{ |
| 74 |
|
Self result; |
| 75 |
|
for (unsigned int i=0; i < VOffsetDimension; i++) |
| 76 |
|
{ result[i] = m_Offset[i] + size[i]; } |
| 77 |
|
return result; |
| 78 |
|
} |
| 79 |
|
|
| 80 |
|
/** Increment index by a size. */ |
| 81 |
|
const Self & |
| 82 |
|
operator+=(const Size<VOffsetDimension> &size) |
| 83 |
|
{ |
| 84 |
|
for (unsigned int i=0; i < VOffsetDimension; i++) |
| 85 |
|
{ m_Offset[i] += size[i]; } |
| 86 |
|
return *this; |
| 87 |
|
} |
| 88 |
|
|
| 89 |
|
/** Decrement index by a size. */ |
| 90 |
|
const Self & |
| 91 |
|
operator-=(const Size<VOffsetDimension> &size) |
| 92 |
|
{ |
| 93 |
|
for (unsigned int i=0; i < VOffsetDimension; i++) |
| 94 |
|
{ m_Offset[i] -= size[i]; } |
| 95 |
|
return *this; |
| 96 |
|
} |
| 97 |
|
|
| 98 |
|
/** Subtract two offsets. */ |
| 99 |
|
const Self |
| 100 |
|
operator-(const Self &vec) |
| 101 |
|
{ |
| 102 |
|
Self result; |
| 103 |
|
for (unsigned int i=0; i < VOffsetDimension; i++) |
| 104 |
|
{ result[i] = m_Offset[i] - vec.m_Offset[i]; } |
| 105 |
|
return result; |
| 106 |
|
} |
| 107 |
|
|
| 108 |
|
/** Increment offset by an offset. */ |
| 109 |
|
const Self & |
| 110 |
|
operator+=(const Self &vec) |
| 111 |
|
{ |
| 112 |
|
for (unsigned int i=0; i < VOffsetDimension; i++) |
| 113 |
|
{ m_Offset[i] += vec.m_Offset[i]; } |
| 114 |
|
return *this; |
| 115 |
|
} |
| 116 |
|
|
| 117 |
|
/** Decrement offset by an offset. */ |
| 118 |
|
const Self & |
| 119 |
|
operator-=(const Self &vec) |
| 120 |
|
{ |
| 121 |
|
for (unsigned int i=0; i < VOffsetDimension; i++) |
| 122 |
|
{ m_Offset[i] -= vec.m_Offset[i]; } |
| 123 |
|
return *this; |
| 124 |
|
} |
| 125 |
|
|
| 126 |
|
/** Compare two offsets. */ |
| 127 |
|
bool |
| 128 |
|
operator==(const Self &vec) const |
| 129 |
|
{ |
| 130 |
|
bool same=1; |
| 131 |
|
for (unsigned int i=0; i < VOffsetDimension && same; i++) |
| 132 |
|
{ same = (m_Offset[i] == vec.m_Offset[i]); } |
| 133 |
|
return same; |
| 134 |
|
} |
| 135 |
|
|
| 136 |
|
/** Compare two offsets. */ |
| 137 |
|
bool |
| 138 |
|
operator!=(const Self &vec) const |
| 139 |
|
{ |
| 140 |
|
bool same=1; |
| 141 |
|
for (unsigned int i=0; i < VOffsetDimension && same; i++) |
| 142 |
|
{ same = (m_Offset[i] == vec.m_Offset[i]); } |
| 143 |
|
return !same; |
| 144 |
|
} |
| 145 |
|
|
| 146 |
|
/** Access an element of the offset. Elements are numbered |
| 147 |
|
* 0, ..., VOffsetDimension-1. No bounds checking is performed. */ |
| 148 |
|
OffsetValueType & operator[](unsigned int dim) |
| 149 |
|
{ return m_Offset[dim]; } |
| 150 |
|
|
| 151 |
|
/** Access an element of the index. Elements are numbered |
| 152 |
|
* 0, ..., VOffsetDimension-1. This version can only be an rvalue. |
| 153 |
|
* No bounds checking is performed. */ |
| 154 |
|
OffsetValueType operator[](unsigned int dim) const |
| 155 |
|
{ return m_Offset[dim]; } |
| 156 |
|
|
| 157 |
|
/** Get the index. This provides a read only reference to the index. |
| 158 |
|
* \sa SetOffset() */ |
| 159 |
|
const OffsetValueType *GetOffset() const { return m_Offset; }; |
| 160 |
|
|
| 161 |
|
/** Set the index. |
| 162 |
|
* Try to prototype this function so that val has to point to a block of |
| 163 |
|
* memory that is the appropriate size. |
| 164 |
|
* \sa GetOffset() */ |
| 165 |
|
void SetOffset(const OffsetValueType val[VOffsetDimension]) |
| 166 |
|
{ memcpy(m_Offset, val, sizeof(OffsetValueType)*VOffsetDimension); } |
| 167 |
|
|
| 168 |
|
/** Return a basis vector of the form [0, ..., 0, 1, 0, ... 0] where the "1" |
| 169 |
|
* is positioned in the location specified by the parameter "dim". Valid |
| 170 |
|
* values of "dim" are 0, ..., VOffsetDimension-1. */ |
| 171 |
|
static Self GetBasisOffset(unsigned int dim); |
| 172 |
|
|
| 173 |
|
/** Set one value for the offset in all dimensions. Useful for initializing |
| 174 |
|
* an offset to zero. */ |
| 175 |
|
void Fill(OffsetValueType value) |
| 176 |
|
{ for(unsigned int i=0;i < VOffsetDimension; ++i) m_Offset[i] = value; } |
| 177 |
|
|
| 178 |
|
/** Offset is an "aggregate" class. Its data is public (m_Offset) |
| 179 |
|
* allowing for fast and convienent instantiations/assignments. |
| 180 |
|
* |
| 181 |
|
* The following syntax for assigning an index is allowed/suggested: |
| 182 |
|
* Offset<3> index = {5, 2, 7}; */ |
| 183 |
|
OffsetValueType m_Offset[VOffsetDimension]; |
| 184 |
|
|
| 185 |
|
}; |
| 186 |
|
|
| 187 |
|
|
| 188 |
|
template<unsigned int VOffsetDimension> |
| 189 |
|
Offset<VOffsetDimension> |
| 190 |
|
Offset<VOffsetDimension> |
| 191 |
|
::GetBasisOffset(unsigned int dim) |
| 192 |
|
{ |
| 193 |
|
Self ind; |
| 194 |
|
|
| 195 |
|
memset(ind.m_Offset, 0, sizeof(OffsetValueType)*VOffsetDimension); |
| 196 |
|
ind.m_Offset[dim] = 1; |
| 197 |
|
return ind; |
| 198 |
|
} |
| 199 |
|
|
| 200 |
|
template<unsigned int VOffsetDimension> |
| 201 |
|
std::ostream & operator<<(std::ostream &os, const Offset<VOffsetDimension> &ind) |
| 202 |
|
{ |
| 203 |
|
os << "["; |
| 204 |
|
unsigned int dimlim = VOffsetDimension - 1; |
| 205 |
|
for (unsigned int i=0; i < dimlim; ++i) |
| 206 |
|
{ |
| 207 |
|
os << ind[i] << ", "; |
| 208 |
|
} |
| 209 |
|
if (VOffsetDimension >= 1) |
| 210 |
|
{ |
| 211 |
|
os << ind[VOffsetDimension-1]; |
| 212 |
|
} |
| 213 |
|
os << "]"; |
| 214 |
|
return os; |
| 215 |
|
} |
| 216 |
|
|
| 217 |
|
} // end namespace itk |
| 218 |
|
|
| 219 |
|
#endif |
| 220 |
|
|