Orfeo Toolbox  3.16
itkConstNeighborhoodIterator.txx
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Insight Segmentation & Registration Toolkit
4  Module: $RCSfile: itkConstNeighborhoodIterator.txx,v $
5  Language: C++
6  Date: $Date: 2006-08-02 11:48:41 $
7  Version: $Revision: 1.27 $
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 __itkConstNeighborhoodIterator_txx
18 #define __itkConstNeighborhoodIterator_txx
20 namespace itk {
21 
22 template<class TImage, class TBoundaryCondition>
23 bool
25 ::InBounds() const
26 {
27  if (m_IsInBoundsValid)
28  {
29  return m_IsInBounds;
30  }
31 
32  bool ans = true;
33  for (unsigned int i=0; i<Dimension; i++)
34  {
35  if (m_Loop[i] < m_InnerBoundsLow[i] || m_Loop[i] >= m_InnerBoundsHigh[i])
36  {
37  m_InBounds[i] = ans = false;
38  }
39  else
40  {
41  m_InBounds[i] = true;
42  }
43  }
44  m_IsInBounds = ans;
45  m_IsInBoundsValid = true;
46  return ans;
47 }
48 
49 
50 template<class TImage, class TBoundaryCondition>
53 ::GetPixel(const unsigned n, bool& IsInBounds) const
54 {
55  // If the region the iterator is walking (padded by the neighborhood size)
56  // never bumps up against the bounds of the buffered region, then don't
57  // bother checking any boundary conditions
58  if (!m_NeedToUseBoundaryCondition)
59  {
60  IsInBounds = true;
61  return (m_NeighborhoodAccessorFunctor.Get(this->operator[](n)));
62  }
63 
64  register unsigned int i;
65  OffsetValueType OverlapLow, OverlapHigh;
66  OffsetType temp, offset;
67  bool flag;
68 
69  // Is this whole neighborhood in bounds?
70  if (this->InBounds())
71  {
72  IsInBounds = true;
73  return (m_NeighborhoodAccessorFunctor.Get(this->operator[](n)));
74  }
75  else
76  {
77  temp = this->ComputeInternalIndex(n);
78 
79  flag = true;
80 
81  // Is this pixel in bounds?
82  for (i=0; i<Dimension; ++i)
83  {
84  if (m_InBounds[i])
85  {
86  offset[i] = 0; // this dimension in bounds
87  }
88  else // part of this dimension spills out of bounds
89  {
90  // Calculate overlap for this dimension
91  OverlapLow = m_InnerBoundsLow[i] - m_Loop[i];
92  OverlapHigh =
93  static_cast<OffsetValueType>(this->GetSize(i) -
94  ( (m_Loop[i]+2) - m_InnerBoundsHigh[i] ));
95 
96  //
97  if (temp[i] < OverlapLow)
98  {
99  flag = false;
100  offset[i] = OverlapLow - temp[i];
101  }
102  else if ( OverlapHigh < temp[i] )
103  {
104  flag = false;
105  offset[i] = OverlapHigh - temp[i];
106  }
107  else offset[i] = 0;
108  }
109  }
110 
111  if (flag)
112  {
113  IsInBounds = true;
114  return ( m_NeighborhoodAccessorFunctor.Get(this->operator[](n)) );
115  }
116  else
117  {
118  IsInBounds = false;
119  return( m_NeighborhoodAccessorFunctor.BoundaryCondition(
120  temp, offset, this, this->m_BoundaryCondition) );
121  }
122  }
123 }
124 
125 
126 template<class TImage, class TBoundaryCondition>
129 ::ComputeInternalIndex(unsigned int n) const
130 {
131  OffsetType ans;
132  long D = (long)Dimension;
133  unsigned long r;
134  r = (unsigned long)n;
135  for (long i = D-1; i >= 0; --i)
136  {
137  ans[i] = static_cast<OffsetValueType>(r / this->GetStride(i));
138  r = r % this->GetStride(i);
139  }
140  return ans;
141 }
142 
143 
144 template <class TImage, class TBoundaryCondition>
148 {
149  RegionType ans;
150  typename IndexType::IndexValueType zero = 0;
151  ans.SetIndex(this->GetIndex(zero));
152  ans.SetSize(this->GetSize());
153 
154  return ans;
155 }
156 
157 template<class TImage, class TBoundaryCondition>
160 {
161  IndexType zeroIndex; zeroIndex.Fill(0);
162  SizeType zeroSize; zeroSize.Fill(0);
163 
164  m_Bound.Fill(0);
165  m_Begin = 0;
166  m_BeginIndex.Fill(0);
167  // m_ConstImage
168  m_End = 0;
169  m_EndIndex.Fill(0);
170  m_Loop.Fill(0);
171  m_Region.SetIndex(zeroIndex);
172  m_Region.SetSize(zeroSize);
173 
174  m_WrapOffset.Fill(0);
175 
176  for (unsigned int i=0; i < Dimension; i++)
177  { m_InBounds[i] = false; }
178 
179  this->ResetBoundaryCondition();
180 
181  m_IsInBounds = false;
182  m_IsInBoundsValid = false;
183 }
184 
185 template<class TImage, class TBoundaryCondition>
187 ::ConstNeighborhoodIterator(const Self& orig)
188  : Neighborhood<InternalPixelType *, Dimension>(orig)
189 {
190  m_Bound = orig.m_Bound;
191  m_Begin = orig.m_Begin;
192  m_BeginIndex = orig.m_BeginIndex;
193  m_ConstImage = orig.m_ConstImage;
194  m_End = orig.m_End;
195  m_EndIndex = orig.m_EndIndex;
196  m_Loop = orig.m_Loop;
197  m_Region = orig.m_Region;
198  m_WrapOffset = orig.m_WrapOffset;
199 
200  m_InternalBoundaryCondition = orig.m_InternalBoundaryCondition;
201  m_NeedToUseBoundaryCondition = orig.m_NeedToUseBoundaryCondition;
202  for (unsigned int i = 0; i < Dimension; ++i)
203  {
204  m_InBounds[i] = orig.m_InBounds[i];
205  }
206  m_IsInBoundsValid = orig.m_IsInBoundsValid;
207  m_IsInBounds = orig.m_IsInBounds;
208 
209  m_InnerBoundsLow = orig.m_InnerBoundsLow;
210  m_InnerBoundsHigh = orig.m_InnerBoundsHigh;
211 
212  // Check to see if the default boundary
213  // conditions have been overridden.
214  if ( orig.m_BoundaryCondition ==
215  static_cast<ImageBoundaryConditionConstPointerType>(
216  &orig.m_InternalBoundaryCondition ))
217  {
218  this->ResetBoundaryCondition();
219  }
220  else
221  { m_BoundaryCondition = orig.m_BoundaryCondition; }
222 
223  m_NeighborhoodAccessorFunctor = orig.m_NeighborhoodAccessorFunctor;
224 
225 }
226 
227 template<class TImage, class TBoundaryCondition>
228 void
231 {
232  if (m_Region.GetNumberOfPixels() > 0)
233  {
234  m_EndIndex = m_Region.GetIndex();
235  m_EndIndex[Dimension-1] = m_Region.GetIndex()[Dimension-1] +
236  static_cast<long>(m_Region.GetSize()[Dimension-1]);
237  }
238  else
239  {
240  // Region has no pixels, so set the end index to be the begin index
241  m_EndIndex = m_Region.GetIndex();
242  }
243 }
244 
245 template<class TImage, class TBoundaryCondition>
249 {
250  register unsigned int i;
251  OffsetType OverlapLow, OverlapHigh, temp, offset;
252  bool flag;
253 
254  const ConstIterator _end = this->End();
255  NeighborhoodType ans;
256  typename NeighborhoodType::Iterator ans_it;
257  ConstIterator this_it;
258 
259  ans.SetRadius( this->GetRadius() );
260 
261  if (m_NeedToUseBoundaryCondition == false)
262  {
263  for (ans_it = ans.Begin(), this_it = this->Begin();
264  this_it < _end; ans_it++, this_it++)
265  { *ans_it = m_NeighborhoodAccessorFunctor.Get(*this_it); }
266  }
267  else if (InBounds())
268  {
269  for (ans_it = ans.Begin(), this_it = this->Begin();
270  this_it < _end; ans_it++, this_it++)
271  { *ans_it = m_NeighborhoodAccessorFunctor.Get(*this_it); }
272  }
273  else
274  {
275  // Calculate overlap & initialize index
276  for (i=0; i<Dimension; i++)
277  {
278  OverlapLow[i] = m_InnerBoundsLow[i] - m_Loop[i];
279  OverlapHigh[i]=
280  static_cast<OffsetValueType>(this->GetSize(i)) - ( (m_Loop[i]+2)
281  - m_InnerBoundsHigh[i] );
282  temp[i] = 0;
283  }
284 
285  // Iterate through neighborhood
286  for (ans_it = ans.Begin(), this_it = this->Begin();
287  this_it < _end; ans_it++, this_it++)
288  {
289  flag = true;
290 
291  // Is this pixel in bounds?
292  for (i=0; i<Dimension; ++i)
293  {
294  if (m_InBounds[i]) offset[i] = 0; // this dimension in bounds
295  else // part of this dimension spills out of bounds
296  {
297  if (temp[i] < OverlapLow[i])
298  {
299  flag = false;
300  offset[i] = OverlapLow[i] - temp[i];
301  }
302  else if ( OverlapHigh[i] < temp[i] )
303  {
304  flag = false;
305  offset[i] = OverlapHigh[i] - temp[i];
306  }
307  else offset[i] = 0;
308  }
309  }
310 
311  if (flag) *ans_it = m_NeighborhoodAccessorFunctor.Get(*this_it);
312  else *ans_it = m_NeighborhoodAccessorFunctor.BoundaryCondition(
313  temp, offset, this, this->m_BoundaryCondition);
314 
315  m_BoundaryCondition->operator()(temp, offset, this);
316 
317  for (i=0; i<Dimension; ++i) // Update index
318  {
319  temp[i]++;
320  if ( temp[i] == static_cast<OffsetValueType>(this->GetSize(i)) )
321  temp[i]= 0;
322  else break;
323  }
324  }
325  }
326  return ans;
327 }
328 
329 template<class TImage, class TBoundaryCondition>
330 void
333 {
334  this->SetLocation( m_BeginIndex );
335 }
336 
337 template<class TImage, class TBoundaryCondition>
338 void
341 {
342  this->SetLocation( m_EndIndex );
343 }
344 
345 template<class TImage, class TBoundaryCondition>
347 ::Initialize(const SizeType &radius, const ImageType *ptr,
348  const RegionType &region)
349 {
350  m_ConstImage = ptr;
351  m_Region = region;
352  const IndexType regionIndex = region.GetIndex();
353 
354  this->SetRadius(radius);
355  this->SetBeginIndex(region.GetIndex());
356  this->SetLocation(region.GetIndex());
357  this->SetBound(region.GetSize());
358  this->SetEndIndex();
359 
360  m_Begin = ptr->GetBufferPointer() + ptr->ComputeOffset(regionIndex);
361 
362  m_End = ptr->GetBufferPointer() + ptr->ComputeOffset( m_EndIndex );
363 
364  // now determine whether boundary conditions are going to be needed
365  const IndexType bStart = ptr->GetBufferedRegion().GetIndex();
366  const SizeType bSize = ptr->GetBufferedRegion().GetSize();
367  const IndexType rStart = region.GetIndex();
368  const SizeType rSize = region.GetSize();
369 
370  long overlapLow, overlapHigh;
371 
372  m_NeedToUseBoundaryCondition = false;
373  for (unsigned long i = 0; i < Dimension; ++i)
374  {
375  overlapLow = static_cast<long>((rStart[i] - radius[i]) - bStart[i]);
376  overlapHigh= static_cast<long>((bStart[i] + bSize[i]) -
377  (rStart[i] + rSize[i] + radius[i]));
378 
379  if (overlapLow < 0) // out of bounds condition, define a region of
380  {
381  m_NeedToUseBoundaryCondition = true;
382  break;
383  }
384 
385  if (overlapHigh < 0)
386  {
387  m_NeedToUseBoundaryCondition = true;
388  break;
389  }
390  }
391 
392  m_IsInBoundsValid = false;
393  m_IsInBounds = false;
394 }
395 
396 template<class TImage, class TBoundaryCondition>
399 ::operator=(const Self& orig)
400 {
401  Superclass::operator=(orig);
402 
403  m_Bound = orig.m_Bound;
404  m_Begin = orig.m_Begin;
405  m_ConstImage = orig.m_ConstImage;
406  m_End = orig.m_End;
407  m_EndIndex = orig.m_EndIndex;
408  m_Loop = orig.m_Loop;
409  m_Region = orig.m_Region;
410  m_BeginIndex = orig.m_BeginIndex;
411  m_WrapOffset = orig.m_WrapOffset;
412 
413  m_InternalBoundaryCondition = orig.m_InternalBoundaryCondition;
414  m_NeedToUseBoundaryCondition = orig.m_NeedToUseBoundaryCondition;
415 
416  m_InnerBoundsLow = orig.m_InnerBoundsLow;
417  m_InnerBoundsHigh = orig.m_InnerBoundsHigh;
418 
419  for (unsigned int i = 0; i < Dimension; ++i)
420  {
421  m_InBounds[i] = orig.m_InBounds[i];
422  }
423  m_IsInBoundsValid = orig.m_IsInBoundsValid;
424  m_IsInBounds = orig.m_IsInBounds;
425 
426  // Check to see if the default boundary conditions
427  // have been overridden.
428  if (orig.m_BoundaryCondition ==
429  static_cast<ImageBoundaryConditionConstPointerType>(
431  {
432  this->ResetBoundaryCondition();
433  }
434  else m_BoundaryCondition = orig.m_BoundaryCondition;
435  m_NeighborhoodAccessorFunctor = orig.m_NeighborhoodAccessorFunctor;
436 
437  return *this;
438 }
439 
440 template<class TImage, class TBoundaryCondition>
444 {
445  unsigned int i;
446  Iterator it;
447  const Iterator _end = Superclass::End();
448 
449  // Repositioning neighborhood, previous bounds check on neighborhood
450  // location is invalid.
451  m_IsInBoundsValid = false;
452 
453  // Increment pointers.
454  for (it = Superclass::Begin(); it < _end; ++it)
455  {
456  (*it)++;
457  }
458 
459  // Check loop bounds, wrap & add pointer offsets if needed.
460  for (i=0; i<Dimension; ++i)
461  {
462  m_Loop[i]++;
463  if ( m_Loop[i] == m_Bound[i] )
464  {
465  m_Loop[i] = m_BeginIndex[i];
466  for (it = Superclass::Begin(); it < _end; ++it)
467  {
468  (*it) += m_WrapOffset[i];
469  }
470  }
471  else break;
472  }
473  return *this;
474 }
475 
476 template<class TImage, class TBoundaryCondition>
480 {
481  unsigned int i;
482  Iterator it;
483  const Iterator _end = Superclass::End();
484 
485  // Repositioning neighborhood, previous bounds check on neighborhood
486  // location is invalid.
487  m_IsInBoundsValid = false;
488 
489  // Decrement pointers.
490  for (it = Superclass::Begin(); it < _end; ++it)
491  {
492  (*it)--;
493  }
494 
495  // Check loop bounds, wrap & add pointer offsets if needed.
496  for (i=0; i<Dimension; ++i)
497  {
498  if (m_Loop[i] == m_BeginIndex[i])
499  {
500  m_Loop[i]= m_Bound[i] - 1;
501  for (it = Superclass::Begin(); it < _end; ++it)
502  {
503  (*it) -= m_WrapOffset[i];
504  }
505  }
506  else
507  {
508  m_Loop[i]--;
509  break;
510  }
511  }
512  return *this;
513 }
514 
515 template<class TImage, class TBoundaryCondition>
516 void
518 ::PrintSelf(std::ostream &os, Indent indent) const
519 {
520  unsigned int i;
521  os << indent;
522  os << "ConstNeighborhoodIterator {this= " << this;
523  os << ", m_Region = { Start = {";
524  for (i=0; i < Dimension; ++i) os << m_Region.GetIndex()[i] << " ";
525  os << "}, Size = { ";
526  for (i=0; i < Dimension; ++i) os << m_Region.GetSize()[i] << " ";
527  os << "} }";
528  os << ", m_BeginIndex = { ";
529  for (i=0; i < Dimension; ++i) os << m_BeginIndex[i] << " ";
530  os << "} , m_EndIndex = { ";
531  for (i=0; i < Dimension; ++i) os << m_EndIndex[i] << " ";
532  os << "} , m_Loop = { ";
533  for (i=0; i < Dimension; ++i) os << m_Loop[i] << " ";
534  os << "}, m_Bound = { ";
535  for (i=0; i < Dimension; ++i) os << m_Bound[i] << " ";
536  os << "}, m_IsInBounds = {" << m_IsInBounds;
537  os << "}, m_IsInBoundsValid = {" << m_IsInBoundsValid;
538  os << "}, m_WrapOffset = { ";
539  for (i=0; i < Dimension; ++i) os << m_WrapOffset[i] << " ";
540  os << ", m_Begin = " << m_Begin;
541  os << ", m_End = " << m_End;
542  os << "}" << std::endl;
543 
544  os << indent << ", m_InnerBoundsLow = { ";
545  for (i = 0; i<Dimension; i++) os << m_InnerBoundsLow[i] << " ";
546  os << "}, m_InnerBoundsHigh = { ";
547  for (i = 0; i<Dimension; i++) os << m_InnerBoundsHigh[i] << " ";
548  os << "} }" << std::endl;
549  Superclass::PrintSelf(os, indent.GetNextIndent());
550 }
551 
552 template<class TImage, class TBoundaryCondition>
554 ::SetBound(const SizeType& size)
555 {
556  SizeType radius = this->GetRadius();
557  const OffsetValueType *offset = m_ConstImage->GetOffsetTable();
558  const IndexType imageBRStart = m_ConstImage->GetBufferedRegion().GetIndex();
559  SizeType imageBRSize = m_ConstImage->GetBufferedRegion().GetSize();
560 
561  // Set the bounds and the wrapping offsets. Inner bounds are the loop
562  // indicies where the iterator will begin to overlap the edge of the image
563  // buffered region.
564  for (unsigned int i=0; i<Dimension; ++i)
565  {
566  m_Bound[i] = m_BeginIndex[i] + static_cast<IndexValueType>(size[i]);
567  m_InnerBoundsHigh[i]= static_cast<IndexValueType>(imageBRStart[i]
568  + ( imageBRSize[i]) - static_cast<SizeValueType>(radius[i]) );
569  m_InnerBoundsLow[i] = static_cast<IndexValueType>(imageBRStart[i]
570  + radius[i]);
571  m_WrapOffset[i] = (static_cast<OffsetValueType>(imageBRSize[i])
572  - ( m_Bound[i] - m_BeginIndex[i] )) * offset[i];
573  }
574  m_WrapOffset[Dimension-1] = 0; // last offset is zero because there are no
575  // higher dimensions
576 }
577 
578 
579 template<class TImage, class TBoundaryCondition>
582 {
583  const Iterator _end = Superclass::End();
584  InternalPixelType * Iit;
585  ImageType *ptr = const_cast<ImageType *>(m_ConstImage.GetPointer());
586  const SizeType size = this->GetSize();
587  const OffsetValueType *OffsetTable = m_ConstImage->GetOffsetTable();
588  const SizeType radius = this->GetRadius();
589 
590  unsigned int i;
591  Iterator Nit;
592  SizeType loop;
593  for (i=0; i<Dimension; ++i) loop[i]=0;
594 
595  // Find first "upper-left-corner" pixel address of neighborhood
596  Iit = ptr->GetBufferPointer() + ptr->ComputeOffset(pos);
597 
598  for (i = 0; i<Dimension; ++i)
599  {
600  Iit -= radius[i] * OffsetTable[i];
601  }
602 
603  // Compute the rest of the pixel addresses
604  for (Nit = Superclass::Begin(); Nit != _end; ++Nit)
605  {
606  *Nit = Iit;
607  ++Iit;
608  for (i = 0; i <Dimension; ++i)
609  {
610  loop[i]++;
611  if ( loop[i] == size[i] )
612  {
613  if (i==Dimension-1) break;
614  Iit += OffsetTable[i+1] - OffsetTable[i] * static_cast<long>(size[i]);
615  loop[i]= 0;
616  }
617  else break;
618  }
619  }
620 }
621 
622 template<class TImage, class TBoundaryCondition>
626 {
627  unsigned int i;
628  Iterator it;
629  const Iterator _end = this->End();
630  OffsetValueType accumulator = 0;
631  const OffsetValueType* stride = this->GetImagePointer()->GetOffsetTable();
632 
633  // Repositioning neighborhood, previous bounds check on neighborhood
634  // location is invalid.
635  m_IsInBoundsValid = false;
636 
637  // Offset from the increment in the lowest dimension
638  accumulator += idx[0];
639 
640  // Offsets from the stride lengths in each dimension.
641  //
642  // Because the image offset table is based on its buffer size and not its
643  // requested region size, we don't have to worry about adding in the wrapping
644  // offsets.
645  for (i = 1; i< Dimension; ++i)
646  {
647  accumulator += idx[i] * stride[i];
648  }
649 
650  // Increment pointers.
651  for (it = this->Begin(); it < _end; ++it)
652  {
653  (*it) += accumulator;
654  }
655 
656  // Update loop counter values
657  m_Loop += idx;
658 
659  return *this;
660 }
661 
662 template<class TImage, class TBoundaryCondition>
666 {
667  unsigned int i;
668  Iterator it;
669  const Iterator _end = this->End();
670  OffsetValueType accumulator = 0;
671  const OffsetValueType* stride = this->GetImagePointer()->GetOffsetTable();
672 
673  // Repositioning neighborhood, previous bounds check on neighborhood
674  // location is invalid.
675  m_IsInBoundsValid = false;
676 
677  // Offset from the increment in the lowest dimension
678  accumulator += idx[0];
679 
680  // Offsets from the stride lengths in each dimension.
681  //
682  // Because the image offset table is based on its buffer size and not its
683  // requested region size, we don't have to worry about adding in the wrapping
684  // offsets.
685  for (i = 1; i< Dimension; ++i)
686  {
687  accumulator += idx[i] * stride[i];
688  }
689 
690  // Increment pointers.
691  for (it = this->Begin(); it < _end; ++it)
692  {
693  (*it) -= accumulator;
694  }
695 
696  // Update loop counter values
697  m_Loop -= idx;
698 
699  return *this;
700 }
701 
702 } // namespace itk
703 
704 #endif

Generated at Sat Feb 2 2013 23:33:22 for Orfeo Toolbox with doxygen 1.8.1.1