aimstil  5.0.5
ConstImageNCVolumetricIterator.h
Go to the documentation of this file.
1 #ifndef TIL_CONSTIMAGENCVOLUMETRICITERATOR_H
2 #define TIL_CONSTIMAGENCVOLUMETRICITERATOR_H
3 
4 // includes from TIL library
5 #include "til/til_common.h"
6 #include "til/labels.h"
7 #include "til/miscTools.h"
8 #include "til/numeric_array.h"
9 #include "til/Range.h"
10 
11 
12 namespace til
13 {
14 
15 // Predeclaration
16 template < typename T > class ImageNC;
17 
18 
19 // A class to iterate through all values of an image while knowing the
20 // image coordinates of the current pixel
21 // Allows to read but not to write to image
22 
23 
24 template < typename T >
25 //class ConstImageNCVolumetricIterator : public VolumetricImageIterator_label
26 class ConstVolumetricIterator<ImageNC<T> > : public VolumetricImageIterator_label
27 {
28 
29 public: // typedefs
30 
31  typedef T value_type;
32  typedef const T & reference;
33  typedef ImageNC<T> TImage;
35  //typedef T StarType;
36 
37 
38 public: // constuctors & destructors
39 
40  // Default constructor
42 
43  // Iterates on the whole image
44  ConstVolumetricIterator<ImageNC<T> >(const ImageNC<T> &im) : m_im(const_cast<ImageNC<T>&>(im)) { this->init(); }
45 
46  // Iterates only on the volume of interest specified by the box
47  ConstVolumetricIterator<ImageNC<T> >(const ImageNC<T> &im, const Range<int,3> & roi) : m_im(im) { this->init(roi); }
48 
50 
51 
52 public: // initialization
53 
54  virtual void init();
55  virtual void init(const Range<int,3> & box);
56 
57 
58 public: // set & get
59 
60  // Get current position
61  /*
62  int getX() const { return m_pos.getX(); }
63  int getY() const { return m_pos.getY(); }
64  int getZ() const { return m_pos.getZ(); }
65  int getPos(int i) const { return m_pos.get(i); }
66  */
67  const numeric_array<int,3> & pos() const { return m_pos; }
68 
69  // Set current position
70  //void setPos(int x, int y, int z);
71  void set_pos(const numeric_array<int,3> & pos);// { this->setPos(EXPAND_VECTOR(pos)); }
72 
73  // Same as above, without range checking
74  //void setUnsafePos(int x, int y, int z);
75  void setUnsafePos(const numeric_array<int,3> &pos);// { this->setUnsafePos(EXPAND_VECTOR(pos)); }
76 
77  // Get the region of interest
78  const Range<int,3> & getRoi() const { return m_roi;}
79 
80  // Get current image
81  const ImageNC<T> & image() const { return m_im; }
82 
83 
84 public: // functions
85 
86 
87  // Get value of a neighbor in an unsafe way
88  // NB: the offset is passed, not the actual position
89  INLINE T getUnsafeValue(int offsetx, int offsety, int offsetz) const
90  {
91  return m_im.getUnsafeValue(
92  this->pos()[0] + offsetx,
93  this->pos()[1] + offsety,
94  this->pos()[2] + offsetz);
95  }
96 
97  template < int offsetx, int offsety, int offsetz >
99  {
100  // TODO: there might be something better to do here, e.g.
101  // newplanebegin - oldplanebegin + m_index + offsetx + offsety * m_offset.getY()
102  // because then the multiplication on getY() is not done for offsety = -1, 0, 1...
103  if (offsetz) return m_im.getUnsafeValue( this->pos()[0] + offsetx, this->pos()[1] + offsety, this->pos()[2] + offsetz);
104  else return *(m_index + offsetx + offsety * m_offset[1] );
105  }
106 
107  template < class Extrapolator, int offsetx, int offsety, int offsetz >
108  INLINE T getValue() const
109  {
110  if (containsNeighbor<offsetx, offsety, offsetz>(*this))
111  {
112  return this->getUnsafeValue<offsetx, offsety, offsetz>();
113  }
114  else
115  {
116  return Extrapolator::getExtrapolatedValue(m_im, this->pos() +
117  numeric_array<int,3>(offsetx, offsety, offsetz));
118 // TODO: Did I broke efficiency again???
119  /*
120  this->pos()[0] + offsetx,
121  this->pos()[1] + offsety,
122  this->pos()[2] + offsetz);
123  */
124  }
125  }
126 
127 
128 
129  template < class Extrapolator >
130  T getValue(int offsetx, int offsety, int offsetz) const
131  {
132  return Extrapolator::getValue(m_im,
133  this->pos()[0] + offsetx,
134  this->pos()[1] + offsety,
135  this->pos()[2] + offsetz);
136  }
137 
138  template < class Extrapolator >
139  T getValue(const numeric_array<int,3> & offset) const
140  {
141  return this->getValue<Extrapolator>(EXPAND_VECTOR(offset));
142  }
143 
144  // Get value of a neighbor
145  // NB: the offset is passed, not the actual position
146  INLINE T operator()(int offsetx, int offsety, int offsetz) const
147  {
148  return m_im.getValue(
149  this->pos()[0] + offsetx,
150  this->pos()[1] + offsety,
151  this->pos()[2] + offsetz);
152  }
153 
155  {
156  return this->operator()(EXPAND_VECTOR(v));
157  }
158 
159 
161 
162 
163  // Print some info about the object
164  //friend void printInfo FRIEND_TEMPLATE_NO_ARG (ConstVolumetricIterator<ImageNC<T> >&);
165 
166 
167  // Got to the next element along given axis
168  INLINE void next(ImageAxis axis);
169  bool isAtEnd() const { return (m_index == 0); }
170  reference operator*() const { return *m_index; }
171 
172  const T * const getIndex() { return m_index; }
173 
174 protected: // data
175 
176  // Current position in the volume
178 
179  // Precomputed offsets to move in each direction
181 
182  // Image
184 
185  // Region of interest in the image
187 
188  // Pointer to current element
190 };
191 
192 
193 
194 
195 
196 
197 
198 
199 
200 
201 
202 
203 
204 
205 
206 
207 
208 
209 
210 
211 
212 
213 
214 
215 
216 
217 
218 
219 
220 
221 
222 
223 
225 //
226 // CODE
227 //
229 
230 
231 template < typename T >
233 {
234  /*
235  if (!isAllocated(im))
236  {
237  m_index = 0;
238  return;
239  }
240  */
241 
242  if (!contains(getRange(m_im), box))
243  {
244  throw std::domain_error("ROI lies outside image range");
245  }
246 
247  m_roi = box;
248  m_pos = box.min_bounds();
249 
250  m_index = m_im.getUnsafePointerOf(m_pos);
251 
252  m_offset[0] = 1;
253  m_offset[1] = m_im.dim()[0];
254  m_offset[2] = m_im.dim()[0]*m_im.dim()[1];
255 }
256 
257 
258 
259 
260 template < typename T >
262 {
263  /*
264  if (!isAllocated(im))
265  {
266  m_index = 0;
267  return;
268  }
269  */
270  this->init(getRange(m_im));
271 }
272 
273 
274 template < typename T >
277 {
278  // We hit a border
279 
280  if (++(m_pos[0]) > m_roi.max_bounds()[0])
281  {
282  m_pos[0] = m_roi.min_bounds()[0];
283 
284  if (++(m_pos[1]) > m_roi.max_bounds()[1])
285  {
286  m_pos[1] = m_roi.min_bounds()[1];
287 
288  if (++(m_pos[2]) > m_roi.max_bounds()[2])
289  {
290  m_index = 0;
291  return *this;
292  }
293  }
294 
295  // TODO: to be faster, use offsets to jump in y and z directions
296  m_index = m_im.getUnsafePointerOf(m_pos);
297  }
298 
299 
300  // We're still in the volume
301 
302  else
303  {
304  ++m_index;
305  }
306 
307  return *this;
308 }
309 
310 /*
311 template < typename T >
312 void ConstVolumetricIterator<ImageNC<T> >::setPos(int x, int y, int z)
313 {
314  if (!contains(m_roi, x, y, z))
315  {
316  throw std::out_of_range("Point does not lie within iterator range");
317  }
318 
319  this->setUnsafePos(x, y, z);
320 }
321 */
322 
323 template < typename T >
325 {
326  if (!contains(m_roi, pos))
327  throw std::out_of_range("Point does not lie within iterator range");
328  this->setUnsafePos(pos);
329 }
330 
331 /*
332 template < typename T >
333 INLINE void ConstVolumetricIterator<ImageNC<T> >::setUnsafePos(int x, int y, int z)
334 {
335  m_pos.setX(x);
336  m_pos.setY(y);
337  m_pos.setZ(z);
338 
339  m_index = m_im.getUnsafePointerOf(m_pos);
340 }
341 */
342 template < typename T >
344 {
345  m_pos = pos;
346  m_index = m_im.getUnsafePointerOf(m_pos);
347 }
348 
349 template < typename T >
350 INLINE void
352 {
353 
354  if (++m_pos[axis] > m_roi.max_bounds()[0])
355  {
356  // We hit a border
357  m_index = 0;
358  }
359  else
360  {
361  // We're still in the volume
362  m_index += m_offset[axis];
363  }
364 }
365 
366 
367 template < typename T >
369 {
370  std::cout << "Pointer: " << it.m_index << std::endl;
371  std::cout << "Position: " << it.m_pos << std::endl;
372  std::cout << "Offset: " << it.m_offset << std::endl;
373  std::cout << "Range: " << it.m_roi.min_bounds() <<" "<< it.m_roi.max_bounds() << std::endl;
374 }
375 
376 } // namespace
377 
378 #endif
INLINE T operator()(const numeric_array< int, 3 > &v) const
#define EXPAND_VECTOR(v)
Definition: til_common.h:54
Belongs to package Box Do not include directly, include til/Box.h instead.
Definition: Accumulator.h:10
void printInfo(ConstVolumetricIterator< ImageNC< T > > &it)
General macros, definitions and functions.
Defines empty classes that serves as labels.
ImageAxis
Definition: miscTools.h:123
const numeric_array< T, D > & min_bounds() const
Get min bounds.
Definition: Box.h:41
INLINE T operator()(int offsetx, int offsety, int offsetz) const
T getValue(int offsetx, int offsety, int offsetz) const
#define INLINE
Definition: til_common.h:26
INLINE T getUnsafeValue(int offsetx, int offsety, int offsetz) const
Image class storing data slice-by-slice.
boost::enable_if< is_numeric_container< TStorage >, bool >::type contains(const Box< T, D > &box, const TStorage &v)
Check whether a point lies within box.
Definition: boxTools.h:15
Range< int, 3 > getRange(const TImage &im)
Get image range.
Definition: imageTools.h:408
T getValue(const numeric_array< int, 3 > &offset) const
TIL_API ImageAxis operator++(ImageAxis &axis)