aimstil  5.0.5
ConstImageVolumetricIterator.h
Go to the documentation of this file.
1 #ifndef TIL_CONSTIMAGECVOLUMETRICITERATOR_H
2 #define TIL_CONSTIMAGECVOLUMETRICITERATOR_H
3 
4 // includes from TIL library
5 #include "til/labels.h"
6 #include "til/numeric_array.h"
7 #include "til/Range.h"
8 #include "til/miscTools.h"
9 
10 
11 // Namespace
12 namespace til {
13 
14 
15  // Predeclaration
16  template < typename T > class ImageC;
17 
18  // A class to iterate through all values of an image while knowing the
19  // image coordinates of the current pixel
20  // Allows to read but not to write to image
21  template < typename T >
22  //class ConstImageCVolumetricIterator : public VolumetricImageIterator_label
23  class ConstVolumetricIterator<ImageC<T> > : public VolumetricImageIterator_label
24  {
25  public: // typdefs
26 
27  typedef T value_type;
28  typedef const T & reference;
29  typedef ImageC<T> TImage;
30 
31  public: // constuctors & destructors
32 
33  // default constructor
34  ConstVolumetricIterator<ImageC<T> >() { m_index = 0; m_end = 0; }
35 
36  // Iterates on the whole image
37  ConstVolumetricIterator<ImageC<T> >(const ImageC<T> & im) : m_im(const_cast<ImageC<T>&>(im)) { this->init(); }
38 
39  // Iterates only on the region of interest specified by the box
40  ConstVolumetricIterator<ImageC<T> >(const ImageC<T> & im, const Range<int,3> & roi) : m_im(const_cast<ImageC<T>&>(im)) { this->init(roi); }
41 
43 
44 
45  public: // initialization
46 
47  virtual void init();
48  virtual void init(const Range<int,3> &box);
49 
50 
51  public: // set & get
52 
53  // set current position
54  //void setPos(int x, int y, int z);
55  void set_pos(const numeric_array<int,3> &pos);// { this->setPos(EXPAND_VECTOR(pos)); }
56 
57  //void setUnsafePos(int x, int y, int z);
58  void setUnsafePos(const numeric_array<int,3> &pos);// { this->setUnsafePos(EXPAND_VECTOR(pos)); }
59 
60  /*
61  // get current position
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  */
66  //int getPos(int i) const { return m_pos.get(i); }
67  const numeric_array<int,3> & pos() const { return m_pos; }
68 
69  // Get the region of interest
70  const Range<int,3> & roi() const { return m_roi;}
71 
72  // Get current image
73  const ImageC<T> & image() const { return m_im; }
74 
75 
76  public: // functions
77 
80  INLINE T getUnsafeValue(int offsetx, int offsety, int offsetz) const
81  {
82  return *(m_index + offsetx + m_im.dim()[0]*(offsety + m_im.dim()[1]*offsetz));
83  //return m_im.getUnsafeValue(
84  // this->getX() + offsetx,
85  // this->getY() + offsety,
86  // this->getZ() + offsetz);
87  }
88 
91  template < int offsetx, int offsety, int offsetz >
93  {
94  return *(m_index + offsetx + m_im.dim()[0]*(offsety + m_im.dim()[1]*offsetz));
95  }
96 
100  {
101  //return this->getUnsafeValue(EXPAND_VECTOR(offset));
102  // TODO: a vector-vector functor could actually take care of this
103  return *(m_index + offset[0] + m_im.dim()[0]*(offset[1] + m_im.dim()[1]*offset[2]));
104  }
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() + til::numeric_array<int,3>(offsetx, offsety, offsetz));
117 /* this->pos()[0] + offsetx,
118  this->pos()[1] + offsety,
119  this->pos()[2] + offsetz);*/
120  }
121  }
122 
126  /*
127  template < class Extrapolator >
128  T getValue(int offsetx, int offsety, int offsetz) const
129  {
130  // NB: here we keep this test and do not call directly
131  // Extrapolator::getValue because we can access the neighbors
132  // faster here than using im.getValue
133  if (contains(m_im,
134  this->getX() + offsetx,
135  this->getY() + offsety,
136  this->getZ() + offsetz))
137  {
138  return this->getUnsafeValue(offsetx, offsety, offsetz);
139  }
140  else
141  {
142  return Extrapolator::getExtrapolatedValue(m_im,
143  this->getX() + offsetx,
144  this->getY() + offsety,
145  this->getZ() + offsetz);
146  }
147  }
148  */
149 
153  template < class Extrapolator >
154  T getValue(const numeric_array<int,3> & offset) const
155  {
156  // NB: here we keep this test and do not call directly
157  // Extrapolator::getValue because we can access the neighbors
158  // faster here than using im.getValue
159  if (contains(m_im, m_pos + offset))
160  {
161  return this->getUnsafeValue(offset);
162  }
163  else
164  {
165  return Extrapolator::getExtrapolatedValue(m_im, m_pos + offset);
166  }
167  //return this->getValue<Extrapolator>(EXPAND_VECTOR(offset));
168  }
169 
170  // Get value of a neighbor
171  // NB: the offset is passed, not the actual position
172  // TODO: hey, why do we need this operator for, with all the
173  // previous methods?
174  /*
175  T operator()(int offsetx, int offsety, int offsetz) const
176  {
177  return m_im.getValue(
178  this->getX() + offsetx,
179  this->getY() + offsety,
180  this->getZ() + offsetz);
181  }
182  */
183 
184  INLINE T operator()(const numeric_array<int,3> &offset) const
185  {
186  //return this->operator()(EXPAND_VECTOR(offset));
187  return m_im.getValue(m_pos + offset);
188  }
189 
191  INLINE void operator++();
192 
194  INLINE bool next();
195 
196  // Print some info about the object
197  // friend void printInfo FRIEND_TEMPLATE_NO_ARG (ConstImageCVolumetricIterator<T> &);
198 
200  INLINE void next(ImageAxis axis);
201 
203  INLINE bool isAtEnd() const { return (m_index == 0); }
204 
206  reference operator*() const { return *m_index; }
207 
208 
209  public: // set & get
210  //protected: // set & get
211 
212  T * getIndex() const { return m_index; }
213 
214 
215  private: // functions
216 
217  void _next();
218 
219  private: // data
220 
221  // Current position in the volume
222  numeric_array<int,3> m_pos;
223 
224  // Precomputed offsets to move in each direction
225  numeric_array<int,3> m_offset;
226 
227  // ImageC
228  ImageC<T> & m_im;
229 
230  // Region of interest in the image
231  Range<int,3> m_roi;
232 
233  // Pointer to current element
234  T* m_index;
235 
236  // Pointer on the last element
237  T* m_end;
238  };
239 
240  template < typename T >
242  {
243  /*
244  if (!isAllocated(im))
245  {
246  m_index = 0;
247  m_end = 0;
248  return;
249  }
250  */
251 
252  if (!contains(getRange(m_im), box))
253  {
254  throw std::domain_error("ROI lies outside image range");
255  }
256 
257  m_roi = box;
258  m_pos = box.min_bounds();
259 
260  m_index = m_im.getUnsafePointerOf(m_pos);
261  m_end = m_im.getUnsafePointerOf(numeric_array<int,3>(box.max_bounds()));
262 
263  m_offset[0] = 1;
264  m_offset[1] = m_im.dim()[0];
265  m_offset[2] = m_im.dim()[0]*m_im.dim()[1];
266  }
267 
268 
269  template < typename T >
271  {
272  /*
273  if (!isAllocated(im))
274  {
275  m_index = 0;
276  return;
277  }
278  */
279  this->init(getRange(m_im));
280  }
281 
282 
283  template < typename T >
284  void ConstVolumetricIterator<ImageC<T> >::_next()
285  {
286  m_pos[0] = m_roi.min_bounds()[0];
287 
288  if (++(m_pos[1]) > m_roi.max_bounds()[1])
289  {
290  m_pos[1] = m_roi.min_bounds()[1];
291 
292  if (++(m_pos[2]) > m_roi.max_bounds()[2])
293  {
294  m_index = 0;
295  //return *this;
296  return;
297  }
298  }
299 
300  // TODO: to be faster, use offsets to jump in y and z directions
301  m_index = m_im.getUnsafePointerOf(m_pos);
302  }
303 
304  template < typename T >
305  //INLINE ConstImageCVolumetricIterator<T> &
306  INLINE void
308  {
309  // We hit a border
310 
311  if (++(m_pos[0]) > m_roi.max_bounds()[0])
312  //if (++(m_pos.m_values[0]) > m_roi.m_posMax.m_values[0])
313  //if (++(m_pos.m_values[0]) > m_roi.getXMax())
314  {
315  this->_next();
316  }
317  // We're still in the volume
318 
319  else
320  {
321  ++m_index;
322  }
323 
324  //return *this;
325  }
326 
327  template < typename T >
329  {
330  if (!contains(m_roi, pos))
331  throw std::out_of_range("Point does not lie within iterator range");
332  this->setUnsafePos(pos);
333  }
334 
335  /*
336  template < typename T >
337  void ConstVolumetricIterator<ImageC<T> > ::setPos(int x, int y, int z)
338  {
339  if (!contains(m_roi, x, y, z))
340  {
341  throw std::out_of_range("Point does not lie within iterator range");
342  }
343 
344  this->setUnsafePos(x,y,z);
345  }
346  */
347 
348  template < typename T >
349  inline void ConstVolumetricIterator<ImageC<T> >::setUnsafePos(const numeric_array<int,3> & pos)
350  {
351  m_pos = pos;
352  m_index = m_im.getUnsafePointerOf(m_pos);
353  }
354 
355  /*
356  template < typename T >
357  inline void ConstVolumetricIterator<ImageC<T> > ::setUnsafePos(int x, int y, int z)
358  {
359  m_pos.setX(x);
360  m_pos.setY(y);
361  m_pos.setZ(z);
362 
363  m_index = m_im.getUnsafePointerOf(m_pos);
364  }
365  */
366 
367  template < typename T >
368  INLINE bool
370  {
371  if (++(m_pos[0]) > m_roi.max_bounds()[0])
372  {
373  m_pos[0] = m_roi.min_bounds()[0];
374  if (++(m_pos[1]) > m_roi.max_bounds()[1])
375  {
376  m_pos[1] = m_roi.min_bounds()[1];
377  if (++(m_pos[2]) > m_roi.max_bounds()[2])
378  {
379  m_index = 0;
380  return false;
381  }
382  }
383  // TODO: to be faster, use offsets to jump in y and z directions
384  m_index = m_im.getUnsafePointerOf(m_pos);
385  }
386  else
387  {
388  ++m_index;
389  }
390  return true;
391  }
392 
393  template < typename T >
394  INLINE void
396  {
397  if (++m_pos[axis] > m_roi.max_bounds()[axis])
398  {
399  // We hit a border
400  m_index = 0;
401  }
402  else
403  {
404  // We're still in the volume
405  m_index += m_offset[axis];
406  }
407  }
408 
409 
410  template < typename T >
412  {
413  std::cout << "Pointer: " << it.m_index << std::endl;
414  std::cout << "Position: " << it.m_pos << std::endl;
415  std::cout << "Offset: " << it.m_offset << std::endl;
416  std::cout << "Range: " << it.m_roi.min_bounds() <<" "<< it.m_roi.max_bounds() << std::endl;
417  }
418 
419 } // namespace til
420 
421 #endif
reference operator*() const
Return the value of the current element.
Belongs to package Box Do not include directly, include til/Box.h instead.
Definition: Accumulator.h:10
void printInfo(ConstVolumetricIterator< ImageNC< T > > &it)
INLINE T getUnsafeValue() const
Get value of a neighbor WITHOUT RANGE CHECKING.
Defines empty classes that serves as labels.
INLINE T getUnsafeValue(int offsetx, int offsety, int offsetz) const
Get value of a neighbor WITHOUT RANGE CHECKING.
ImageAxis
Definition: miscTools.h:123
const numeric_array< T, D > & min_bounds() const
Get min bounds.
Definition: Box.h:41
const numeric_array< T, D > & max_bounds() const
Get max bounds.
Definition: Box.h:43
#define INLINE
Definition: til_common.h:26
const numeric_array< int, 3 > & pos() const
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
INLINE bool isAtEnd() const
Test whether the iterator has reached the end of the image or not.
Image class using contiguous memory.
INLINE T getUnsafeValue(const numeric_array< int, 3 > &offset) const
Get value of a neighbor WITHOUT RANGE CHECKING.
T getValue(const numeric_array< int, 3 > &offset) const
Get value of a neighbor.
INLINE T operator()(const numeric_array< int, 3 > &offset) const
TIL_API ImageAxis operator++(ImageAxis &axis)