[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]

multi_iterator_coupled.hxx VIGRA

1 /************************************************************************/
2 /* */
3 /* Copyright 2011-2012 by Stefan Schmidt and Ullrich Koethe */
4 /* */
5 /* This file is part of the VIGRA computer vision library. */
6 /* The VIGRA Website is */
7 /* http://hci.iwr.uni-heidelberg.de/vigra/ */
8 /* Please direct questions, bug reports, and contributions to */
9 /* ullrich.koethe@iwr.uni-heidelberg.de or */
10 /* vigra@informatik.uni-hamburg.de */
11 /* */
12 /* Permission is hereby granted, free of charge, to any person */
13 /* obtaining a copy of this software and associated documentation */
14 /* files (the "Software"), to deal in the Software without */
15 /* restriction, including without limitation the rights to use, */
16 /* copy, modify, merge, publish, distribute, sublicense, and/or */
17 /* sell copies of the Software, and to permit persons to whom the */
18 /* Software is furnished to do so, subject to the following */
19 /* conditions: */
20 /* */
21 /* The above copyright notice and this permission notice shall be */
22 /* included in all copies or substantial portions of the */
23 /* Software. */
24 /* */
25 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
26 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
27 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
28 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
29 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
30 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
31 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
32 /* OTHER DEALINGS IN THE SOFTWARE. */
33 /* */
34 /************************************************************************/
35 
36 #ifndef MULTI_ITERATOR_COUPLED_HXX
37 #define MULTI_ITERATOR_COUPLED_HXX
38 
39 #include "metaprogramming.hxx"
40 #include "multi_shape.hxx"
41 
42 namespace vigra {
43 
44 /** \addtogroup MultiIteratorGroup
45 */
46 //@{
47 
48  /**
49  Handle class, used by CoupledScanOrderIterator as the value type to simultaneously itearate over multiple images.
50  */
51 template <class T, class NEXT>
53 : public NEXT
54 {
55 public:
56  typedef NEXT base_type;
58 
59  static const int index = NEXT::index + 1; // index of this member of the chain
60  static const unsigned int dimensions = NEXT::dimensions;
61 
62  typedef T value_type;
63  typedef T * pointer;
64  typedef T const * const_pointer;
65  typedef T & reference;
66  typedef T const & const_reference;
67  typedef typename base_type::shape_type shape_type;
68 
70  : base_type(),
71  pointer_(),
72  strides_()
73  {}
74 
75  CoupledHandle(const_pointer p, shape_type const & strides, NEXT const & next)
76  : base_type(next),
77  pointer_(const_cast<pointer>(p)),
78  strides_(strides)
79  {}
80 
81  template <class Stride>
82  CoupledHandle(MultiArrayView<dimensions, T, Stride> const & v, NEXT const & next)
83  : base_type(next),
84  pointer_(const_cast<pointer>(v.data())),
85  strides_(v.stride())
86  {
87  vigra_precondition(v.shape() == this->shape(), "createCoupledIterator(): shape mismatch.");
88  }
89 
90  template<int DIMENSION>
91  inline void increment()
92  {
93  pointer_ += strides_[DIMENSION];
94  base_type::template increment<DIMENSION>();
95  }
96 
97  template<int DIMENSION>
98  inline void decrement()
99  {
100  pointer_ -= strides_[DIMENSION];
101  base_type::template decrement<DIMENSION>();
102  }
103 
104  // TODO: test if making the above a default case of the this hurts performance
105  template<int DIMENSION>
106  inline void increment(MultiArrayIndex offset)
107  {
108  pointer_ += offset*strides_[DIMENSION];
109  base_type::template increment<DIMENSION>(offset);
110  }
111 
112  template<int DIMENSION>
113  inline void decrement(MultiArrayIndex offset)
114  {
115  pointer_ -= offset*strides_[DIMENSION];
116  base_type::template decrement<DIMENSION>(offset);
117  }
118 
119  void restrictToSubarray(shape_type const & start, shape_type const & end)
120  {
121  pointer_ += dot(start, strides_);
122  base_type::restrictToSubarray(start, end);
123  }
124 
125  // ptr access
126  reference operator*()
127  {
128  return *pointer_;
129  }
130 
131  const_reference operator*() const
132  {
133  return *pointer_;
134  }
135 
136  pointer operator->()
137  {
138  return pointer_;
139  }
140 
141  const_pointer operator->() const
142  {
143  return pointer_;
144  }
145 
146  pointer ptr()
147  {
148  return pointer_;
149  }
150 
151  const_pointer ptr() const
152  {
153  return pointer_;
154  }
155 
156  shape_type const & strides() const
157  {
158  return strides_;
159  }
160 
161  pointer pointer_;
162  shape_type strides_;
163 };
164 
165 
166 template <int N>
168 {
169 public:
170  static const int index = 0; // index of this member of the chain
171  static const unsigned int dimensions = N;
172 
173  typedef typename MultiArrayShape<N>::type value_type;
174  typedef value_type const * pointer;
175  typedef value_type const * const_pointer;
176  typedef value_type const & reference;
177  typedef value_type const & const_reference;
178  typedef value_type shape_type;
179  typedef CoupledHandle<value_type, void> self_type;
180 
181  CoupledHandle()
182  : point_(),
183  shape_(),
184  scanOrderIndex_()
185  {}
186 
187  CoupledHandle(value_type const & shape)
188  : point_(),
189  shape_(shape),
190  scanOrderIndex_()
191  {}
192 
193  CoupledHandle(typename MultiArrayShape<N+1>::type const & shape)
194  : point_(),
195  shape_(shape.begin()),
196  scanOrderIndex_()
197  {}
198 
199  template<int DIMENSION>
200  inline void increment()
201  {
202  ++point_[DIMENSION];
203  }
204 
205  template<int DIMENSION>
206  inline void decrement()
207  {
208  --point_[DIMENSION];
209  }
210 
211  // TODO: test if making the above a default case of the this hurts performance
212  template<int DIMENSION>
213  inline void increment(MultiArrayIndex offset)
214  {
215  point_[DIMENSION] += offset;
216  }
217 
218  template<int DIMENSION>
219  inline void decrement(MultiArrayIndex offset)
220  {
221  point_[DIMENSION] -= offset;
222  }
223 
224  void restrictToSubarray(shape_type const & start, shape_type const & end)
225  {
226  point_ = shape_type();
227  shape_ = end - start;
228  scanOrderIndex_ = 0;
229  }
230 
231  inline void incrementIndex()
232  {
233  ++scanOrderIndex_;
234  }
235 
236  inline void decrementIndex()
237  {
238  --scanOrderIndex_;
239  }
240 
241  inline void incrementIndex(MultiArrayIndex offset)
242  {
243  scanOrderIndex_ += offset;
244  }
245 
246  inline void decrementIndex(MultiArrayIndex offset)
247  {
248  scanOrderIndex_ -= offset;
249  }
250 
251  // access
252  MultiArrayIndex scanOrderIndex() const
253  {
254  return scanOrderIndex_;
255  }
256 
257  // access
258  const_reference point() const
259  {
260  return point_;
261  }
262 
263  // access
264  const_reference shape() const
265  {
266  return shape_;
267  }
268 
269  const_reference operator*() const
270  {
271  return point_;
272  }
273 
274  const_pointer operator->() const
275  {
276  return &point_;
277  }
278 
279  const_pointer ptr() const
280  {
281  return &point_;
282  }
283 
284  unsigned int borderType() const
285  {
286  return detail::BorderTypeImpl<N>::exec(point_, shape_);
287  }
288 
289  value_type point_, shape_;
290  MultiArrayIndex scanOrderIndex_;
291 };
292 
293 template <unsigned int N, class T, class StrideTag>
294 class MultiArrayView<N, Multiband<T>, StrideTag>
295 : public MultiArrayView<N, T, StrideTag>
296 {
297  public:
298  MultiArrayView(MultiArrayView<N, T, StrideTag> const & v)
299  : MultiArrayView<N, T, StrideTag>(v)
300  {}
301 };
302 
303 template <class T, class NEXT>
304 class CoupledHandle<Multiband<T>, NEXT>
305 : public NEXT
306 {
307 public:
308  typedef NEXT base_type;
309  typedef CoupledHandle<Multiband<T>, NEXT> self_type;
310 
311  static const int index = NEXT::index + 1; // index of this member of the chain
312  static const unsigned int dimensions = NEXT::dimensions;
313 
314  typedef MultiArrayView<1, T, StridedArrayTag> value_type;
315  typedef value_type * pointer;
316  typedef value_type const * const_pointer;
317  typedef value_type & reference;
318  typedef value_type const & const_reference;
319  typedef typename base_type::shape_type shape_type;
320 
321  CoupledHandle()
322  : base_type(),
323  view_(),
324  strides_()
325  {}
326 
327  CoupledHandle(const_reference p, shape_type const & strides, NEXT const & next)
328  : base_type(next),
329  view_(p),
330  strides_(strides)
331  {}
332 
333  template <class Stride>
334  CoupledHandle(MultiArrayView<dimensions+1, Multiband<T>, Stride> const & v, NEXT const & next)
335  : base_type(next),
336  view_(v.bindInner(shape_type())),
337  strides_(v.bindOuter(0).stride())
338  {
339  vigra_precondition(v.bindOuter(0).shape() == this->shape(), "createCoupledIterator(): shape mismatch.");
340  }
341 
342  template<int DIMENSION>
343  inline void increment()
344  {
345  view_.unsafePtr() += strides_[DIMENSION];
346  base_type::template increment<DIMENSION>();
347  }
348 
349  template<int DIMENSION>
350  inline void decrement()
351  {
352  view_.unsafePtr() -= strides_[DIMENSION];
353  base_type::template decrement<DIMENSION>();
354  }
355 
356  // TODO: test if making the above a default case of the this hurts performance
357  template<int DIMENSION>
358  inline void increment(MultiArrayIndex offset)
359  {
360  view_.unsafePtr() += offset*strides_[DIMENSION];
361  base_type::template increment<DIMENSION>(offset);
362  }
363 
364  template<int DIMENSION>
365  inline void decrement(MultiArrayIndex offset)
366  {
367  view_.unsafePtr() -= offset*strides_[DIMENSION];
368  base_type::template decrement<DIMENSION>(offset);
369  }
370 
371  void restrictToSubarray(shape_type const & start, shape_type const & end)
372  {
373  view_.unsafePtr() += dot(start, strides_);
374  base_type::restrictToSubarray(start, end);
375  }
376 
377  // ptr access
378  reference operator*()
379  {
380  return view_;
381  }
382 
383  const_reference operator*() const
384  {
385  return view_;
386  }
387 
388  pointer operator->()
389  {
390  return &view_;
391  }
392 
393  const_pointer operator->() const
394  {
395  return &view_;
396  }
397 
398  pointer ptr()
399  {
400  return &view_;
401  }
402 
403  const_pointer ptr() const
404  {
405  return &view_;
406  }
407 
408  shape_type const & strides() const
409  {
410  return strides_;
411  }
412 
413  value_type view_;
414  shape_type strides_;
415 };
416 
417 template <unsigned TARGET_INDEX>
418 struct Error__CoupledHandle_index_out_of_range;
419 
420 namespace detail {
421 
422 template <unsigned TARGET_INDEX, class Handle, bool isValid, unsigned int INDEX=Handle::index>
423 struct CoupledHandleCastImpl
424 {
425  typedef typename CoupledHandleCastImpl<TARGET_INDEX, typename Handle::base_type, isValid>::type type;
426 };
427 
428 template <unsigned TARGET_INDEX, class Handle, unsigned int INDEX>
429 struct CoupledHandleCastImpl<TARGET_INDEX, Handle, false, INDEX>
430 {
431  typedef Error__CoupledHandle_index_out_of_range<TARGET_INDEX> type;
432 };
433 
434 template <unsigned TARGET_INDEX, class Handle>
435 struct CoupledHandleCastImpl<TARGET_INDEX, Handle, true, TARGET_INDEX>
436 {
437  typedef Handle type;
438 };
439 
440 } // namespace detail
441 
442 template <unsigned TARGET_INDEX, class Handle, unsigned int INDEX=Handle::index>
443 struct CoupledHandleCast
444 : public detail::CoupledHandleCastImpl<TARGET_INDEX, Handle, (TARGET_INDEX <= INDEX), INDEX>
445 {};
446 
447 template <unsigned int TARGET_INDEX, class Handle>
448 typename CoupledHandleCast<TARGET_INDEX, Handle>::type &
449 cast(Handle & handle)
450 {
451  return handle;
452 };
453 
454 template <unsigned int TARGET_INDEX, class Handle>
455 typename CoupledHandleCast<TARGET_INDEX, Handle>::type const &
456 cast(Handle const & handle)
457 {
458  return handle;
459 };
460 
461  /** Returns reference to the element in the band of the handle with index TARGET_INDEX.
462  */
463 template <unsigned int TARGET_INDEX, class Handle>
464 typename CoupledHandleCast<TARGET_INDEX, Handle>::type::reference
465 get(Handle & handle)
466 {
467  return *cast<TARGET_INDEX>(handle);
468 };
469 
470  /** Returns a constant reference to the element in the band of the handle with index TARGET_INDEX.
471  */
472 template <unsigned int TARGET_INDEX, class Handle>
473 typename CoupledHandleCast<TARGET_INDEX, Handle>::type::const_reference
474 get(Handle const & handle)
475 {
476  return *cast<TARGET_INDEX>(handle);
477 };
478 
479 /********************************************************/
480 /* */
481 /* CoupledScanOrderIterator<N> */
482 /* */
483 /********************************************************/
484 
485 /** \brief Iterate over multiple images simultaneously in scan order.
486 
487  The value type of this iterator is an instance of the handle class CoupledHandle. This allows to iterate over multiple arrays simultaneously. The coordinates can be accessed as a special band (index 0) in the handle. The scan-order is defined such that dimensions are iterated from front to back (first to last).
488 
489  Instances of this class are usually constructed by calling createCoupledIterator() .
490 
491  To get the type of a CoupledScanOrderIterator for arrays of a certain dimension and element types use CoupledIteratorType::type.
492 
493  The iterator supports all functions listed in the STL documentation for
494  <a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access Iterators</a>.
495 
496  Example of use:
497  \code
498  using namespace vigra;
499  MultiArray<2, double> image1(Shape2(5, 5));
500  MultiArray<2, double> image2(Shape2(5, 5));
501  // fill image with data ...
502 
503  typedef CoupledIteratorType<2, double, double>::type Iterator; // the type of the CoupledScanOrderIterator
504 
505  Iterator start = createCoupledIterator(image1, image2); // create coupled iterator for simultaneous iteration over image1, image2 and their coordinates
506  Iterator end = start.getEndIterator();
507 
508  for (Iterator it = start; it < end; ++it) {
509  std::cout << "coordinates: " << it.get<0>() << std::endl;
510  std::cout << "image1: " << it.get<1>() << std::endl;
511  std::cout << "image2: " << it.get<2>() << std::endl;
512  }
513 
514  //random access:
515  Iterator::value_type handle = start[15];
516  std::cout << "image1: " << get<1>(handle) << std::endl;
517  \endcode
518 
519  <b>\#include</b> <vigra/multi_iterator_coupled.hxx> <br/>
520  Namespace: vigra
521 */
522 
523 template <unsigned int N,
524  class HANDLES=CoupledHandle<TinyVector<MultiArrayIndex, N>, void>,
525  int DIMENSION = N-1>
526 class CoupledScanOrderIterator
527 #ifndef DOXYGEN // doxygen doesn't understand this inheritance
528 : protected CoupledScanOrderIterator<N, HANDLES, DIMENSION-1>
529 #endif
530 {
531  typedef CoupledScanOrderIterator<N, HANDLES, DIMENSION-1> base_type;
532  static const int dimension = DIMENSION;
533 
534  public:
535 
536  typedef typename MultiArrayShape<dimension+1>::type shape_type;
537  typedef MultiArrayIndex difference_type;
538  typedef CoupledScanOrderIterator iterator;
539  typedef std::random_access_iterator_tag iterator_category;
540 
541  typedef typename base_type::value_type value_type;
542 
543 #ifdef DOXYGEN
544  /** The type of the CoupledHandle.
545  */
546  typedef HANDLES value_type;
547 #endif
548 
549  typedef typename base_type::reference reference;
550  typedef typename base_type::const_reference const_reference; // FIXME: do we need both?
551  typedef typename base_type::pointer pointer;
552 
553  explicit CoupledScanOrderIterator(value_type const & handles = value_type())
554  : base_type(handles)
555  {}
556 
557  value_type operator[](MultiArrayIndex i) const
558  {
559  return *(CoupledScanOrderIterator(*this) += i);
560  }
561 
562  CoupledScanOrderIterator & operator++()
563  {
564  base_type::operator++();
565  if(this->point()[dimension-1] == this->shape()[dimension-1])
566  {
567  base_type::reset();
568  this->handles_.template increment<dimension>();
569  }
570  return *this;
571  }
572 
573  CoupledScanOrderIterator operator++(int)
574  {
575  CoupledScanOrderIterator res(*this);
576  ++*this;
577  return res;
578  }
579 
580  CoupledScanOrderIterator & operator+=(MultiArrayIndex i)
581  {
582  // FIXME: this looks very expensive
583  shape_type coordOffset;
584  detail::ScanOrderToCoordinate<N>::exec(i+scanOrderIndex(), this->shape(), coordOffset);
585  coordOffset -= point();
586  moveRelative(coordOffset);
587  this->handles_.scanOrderIndex_ += i;
588  return *this;
589  }
590 
591  CoupledScanOrderIterator & operator+=(const shape_type &coordOffset)
592  {
593  moveRelative(coordOffset);
594  this->handles_.scanOrderIndex_ += detail::CoordinateToScanOrder<N>::exec(this->shape(), coordOffset);
595  return *this;
596  }
597 
598  CoupledScanOrderIterator & operator--()
599  {
600  base_type::operator--();
601  if(this->point()[dimension-1] == -1)
602  {
603  base_type::inverseReset();
604  this->handles_.template decrement<dimension>();
605  }
606  return *this;
607  }
608 
609  CoupledScanOrderIterator operator--(int)
610  {
611  CoupledScanOrderIterator res(*this);
612  --*this;
613  return res;
614  }
615 
616  CoupledScanOrderIterator & operator-=(MultiArrayIndex i)
617  {
618  return operator+=(-i);
619  }
620 
621  CoupledScanOrderIterator & operator-=(const shape_type &coordOffset)
622  {
623  return operator+=(-coordOffset);
624  }
625 
626  /** Returns CoupledScanOrderIterator pointing beyond the last element.
627  */
629  {
630  return operator+(prod(this->shape()) - this->scanOrderIndex());
631  }
632 
634  {
635  return CoupledScanOrderIterator(*this) += d;
636  }
637 
638  CoupledScanOrderIterator operator-(MultiArrayIndex d) const
639  {
640  return CoupledScanOrderIterator(*this) -= d;
641  }
642 
643  CoupledScanOrderIterator operator+(const shape_type &coordOffset) const
644  {
645  return CoupledScanOrderIterator(*this) += coordOffset;
646  }
647 
648  CoupledScanOrderIterator operator-(const shape_type &coordOffset) const
649  {
650  return CoupledScanOrderIterator(*this) -= coordOffset;
651  }
652 
653  MultiArrayIndex operator-(CoupledScanOrderIterator const & r) const
654  {
655  return base_type::operator-(r);
656  }
657 
658  bool operator==(CoupledScanOrderIterator const & r) const
659  {
660  return base_type::operator==(r);
661  }
662 
663  bool operator!=(CoupledScanOrderIterator const & r) const
664  {
665  return base_type::operator!=(r);
666  }
667 
668  bool operator<(CoupledScanOrderIterator const & r) const
669  {
670  return base_type::operator<(r);
671  }
672 
673  bool operator<=(CoupledScanOrderIterator const & r) const
674  {
675  return base_type::operator<=(r);
676  }
677 
678  bool operator>(CoupledScanOrderIterator const & r) const
679  {
680  return base_type::operator>(r);
681  }
682 
683  bool operator>=(CoupledScanOrderIterator const & r) const
684  {
685  return base_type::operator>=(r);
686  }
687 
688  CoupledScanOrderIterator & restrictToSubarray(shape_type const & start, shape_type const & end)
689  {
690  this->operator+=(-point());
691  this->handles_.restrictToSubarray(start, end);
692  return *this;
693  }
694 
695  using base_type::operator*;
696  using base_type::point;
697  using base_type::shape;
698  using base_type::scanOrderIndex;
699  using base_type::atBorder;
700  using base_type::borderType;
701  using base_type::get;
702  using base_type::isValid;
703  using base_type::atEnd;
704 
705 #ifdef DOXYGEN
706 
707  /** Returns reference to the element in the band with index TARGET_INDEX.
708  */
709  template<unsigned int TARGET_INDEX>
710  typename CoupledHandleCast<TARGET_INDEX, value_type>::type::reference
711  get();
712 
713  /** Returns constant reference to the element in the band with index TARGET_INDEX.
714  */
715  template<unsigned int TARGET_INDEX>
716  typename CoupledHandleCast<TARGET_INDEX, value_type>::type::const_reference
717  get() const;
718 
719 #endif
720 
721  protected:
722  void reset()
723  {
724  this->handles_.template decrement<dimension>(this->shape()[dimension]);
725  }
726 
727  void inverseReset()
728  {
729  this->handles_.template increment<dimension>(this->shape()[dimension]);
730  }
731 
732  void moveRelative(typename value_type::shape_type const & coordOffset)
733  {
734  base_type::moveRelative(coordOffset);
735  this->handles_.template increment<dimension>(coordOffset[dimension]);
736  }
737 };
738 
739 
740 
741 template <unsigned int N, class HANDLES>
742 class CoupledScanOrderIterator<N, HANDLES, 0>
743 {
744  static const int dimension = 0;
745 
746  public:
747 
748  typedef CoupledScanOrderIterator<N, HANDLES, 0> self_type;
749  typedef HANDLES value_type;
750  typedef MultiArrayIndex difference_type;
751  typedef value_type & reference;
752  typedef value_type const & const_reference;
753  typedef value_type * pointer;
754  typedef typename MultiArrayShape<1>::type shape_type;
755  typedef CoupledScanOrderIterator iterator;
756  typedef std::random_access_iterator_tag iterator_category;
757 
758  explicit CoupledScanOrderIterator(value_type const & handles = value_type())
759  : handles_(handles)
760  {}
761 
762  CoupledScanOrderIterator & operator++()
763  {
764  handles_.template increment<dimension>();
765  handles_.incrementIndex();
766  return *this;
767  }
768 
769  CoupledScanOrderIterator operator++(int)
770  {
771  CoupledScanOrderIterator res(*this);
772  ++*this;
773  return res;
774  }
775 
776  CoupledScanOrderIterator & operator+=(MultiArrayIndex i)
777  {
778  shape_type coordOffset;
779  detail::ScanOrderToCoordinate<N>::exec(i, shape(), coordOffset);
780  moveRelative(coordOffset);
781  handles_.scanOrderIndex_ += i;
782  return *this;
783  }
784 
785  CoupledScanOrderIterator & operator+=(const shape_type &coordOffset)
786  {
787  moveRelative(coordOffset);
788  handles_.scanOrderIndex_ += detail::CoordinateToScanOrder<N>::exec(shape(), coordOffset);
789  return *this;
790  }
791 
792  CoupledScanOrderIterator & operator-=(const shape_type &coordOffset)
793  {
794  return operator+=(-coordOffset);
795  }
796 
797  CoupledScanOrderIterator & operator--()
798  {
799  handles_.template decrement<dimension>();
800  handles_.decrementIndex();
801  return *this;
802  }
803 
804  CoupledScanOrderIterator operator--(int)
805  {
806  CoupledScanOrderIterator res(*this);
807  --this;
808  return res;
809  }
810 
811  CoupledScanOrderIterator & operator-=(MultiArrayIndex i)
812  {
813  return operator+=(-i);
814  }
815 
816  value_type operator[](MultiArrayIndex i) const
817  {
818  return *(CoupledScanOrderIterator(*this) += i);
819  }
820 
821  CoupledScanOrderIterator
822  operator+(MultiArrayIndex d) const
823  {
824  return CoupledScanOrderIterator(*this) += d;
825  }
826 
827  CoupledScanOrderIterator
828  operator-(MultiArrayIndex d) const
829  {
830  return CoupledScanOrderIterator(*this) -= d;
831  }
832 
833  CoupledScanOrderIterator operator+(const shape_type &coordOffset) const
834  {
835  return CoupledScanOrderIterator(*this) += coordOffset;
836  }
837 
838  CoupledScanOrderIterator operator-(const shape_type &coordOffset) const
839  {
840  return CoupledScanOrderIterator(*this) -= coordOffset;
841  }
842 
844  operator-(CoupledScanOrderIterator const & r) const
845  {
846  return scanOrderIndex() - r.scanOrderIndex();
847  }
848 
849  bool operator==(CoupledScanOrderIterator const & r) const
850  {
851  return scanOrderIndex() == r.scanOrderIndex();
852  }
853 
854  bool operator!=(CoupledScanOrderIterator const & r) const
855  {
856  return scanOrderIndex() != r.scanOrderIndex();
857  }
858 
859  bool operator<(CoupledScanOrderIterator const & r) const
860  {
861  return scanOrderIndex() < r.scanOrderIndex();
862  }
863 
864  bool operator<=(CoupledScanOrderIterator const & r) const
865  {
866  return scanOrderIndex() <= r.scanOrderIndex();
867  }
868 
869  bool operator>(CoupledScanOrderIterator const & r) const
870  {
871  return scanOrderIndex() > r.scanOrderIndex();
872  }
873 
874  bool operator>=(CoupledScanOrderIterator const & r) const
875  {
876  return scanOrderIndex() >= r.scanOrderIndex();
877  }
878 
879  bool isValid() const
880  {
881  return handles_.scanOrderIndex() < prod(shape());
882  }
883 
884  bool atEnd() const
885  {
886  return handles_.scanOrderIndex() >= prod(shape());
887  }
888 
889  MultiArrayIndex scanOrderIndex() const
890  {
891  return handles_.scanOrderIndex();
892  }
893 
894  typename value_type::shape_type const & point() const
895  {
896  return handles_.point();
897  }
898 
899  typename value_type::shape_type const & shape() const
900  {
901  return handles_.shape();
902  }
903 
904  reference operator*()
905  {
906  return handles_;
907  }
908 
909  const_reference operator*() const
910  {
911  return handles_;
912  }
913 
914  CoupledScanOrderIterator & restrictToSubarray(shape_type const & start, shape_type const & end)
915  {
916  operator+=(-point());
917  handles_.restrictToSubarray(start, end);
918  return *this;
919  }
920 
921  CoupledScanOrderIterator getEndIterator() const
922  {
923  return operator+(prod(shape())-scanOrderIndex());
924  }
925 
926  bool atBorder() const
927  {
928  return (handles_.borderType() != 0);
929  }
930 
931  unsigned int borderType() const
932  {
933  return handles_.borderType();
934  }
935 
936  template<unsigned int TARGET_INDEX>
937  typename CoupledHandleCast<TARGET_INDEX, value_type>::type::reference
938  get()
939  {
940  return vigra::get<TARGET_INDEX>(handles_);
941  }
942 
943  template<unsigned int TARGET_INDEX>
944  typename CoupledHandleCast<TARGET_INDEX, value_type>::type::const_reference
945  get() const
946  {
947  return vigra::get<TARGET_INDEX>(handles_);
948  }
949 
950  protected:
951  void reset()
952  {
953  handles_.template decrement<dimension>(shape()[dimension]);
954  }
955 
956  void inverseReset()
957  {
958  handles_.template increment<dimension>(shape()[dimension]);
959  }
960 
961  void moveRelative(typename value_type::shape_type const & coordOffset)
962  {
963  handles_.template increment<dimension>(coordOffset[dimension]);
964  }
965 
966  value_type handles_;
967 };
968 
969 
970 template <unsigned int N, class List>
971 struct ComposeCoupledHandle;
972 
973 template <unsigned int N, class T, class TAIL>
974 struct ComposeCoupledHandle<N, TypeList<T, TAIL> >
975 {
976  typedef typename ComposeCoupledHandle<N, TAIL>::type BaseType;
977  typedef typename MultiArrayShape<N>::type shape_type;
978  typedef CoupledHandle<T, BaseType> type;
979 
980  template <class S>
981  type exec(MultiArrayView<N, T, S> const & m,
982  shape_type const & start, shape_type const & end,
983  BaseType const & base)
984  {
985  return type(m.subarray(start, end).data(), m.stride(), base);
986  }
987 
988  template <class S>
989  type exec(MultiArrayView<N, T, S> const & m, BaseType const & base)
990  {
991  return type(m.data(), m.stride(), base);
992  }
993 };
994 
995 template <unsigned int N>
996 struct ComposeCoupledHandle<N, void>
997 {
998  typedef typename MultiArrayShape<N>::type shape_type;
999  typedef CoupledHandle<shape_type, void> type;
1000 
1001  type exec(shape_type const & shape)
1002  {
1003  return type(shape);
1004  }
1005 
1006  type exec(shape_type const & start, shape_type const & end)
1007  {
1008  return type(end-start);
1009  }
1010 };
1011 
1012 template <unsigned int N, class T1=void, class T2=void, class T3=void, class T4=void, class T5=void>
1013 struct CoupledHandleType
1014 {
1015  // reverse the order to get the desired index order
1016  typedef typename MakeTypeList<T5, T4, T3, T2, T1>::type TypeList;
1017  typedef typename ComposeCoupledHandle<N, TypeList>::type type;
1018 };
1019 
1020 template <unsigned int N, class T1, class T2, class T3, class T4, class T5>
1021 struct CoupledHandleType<N, Multiband<T1>, T2, T3, T4, T5>
1022 {
1023  // reverse the order to get the desired index order
1024  typedef typename MakeTypeList<T5, T4, T3, T2, Multiband<T1> >::type TypeList;
1025  typedef typename ComposeCoupledHandle<N-1, TypeList>::type type;
1026 };
1027 
1028 /** Helper class to easliy get the type of a CoupledScanOrderIterator (and corresponding CoupledHandle) for up to five arrays of dimension N with element types T1,...,T5.
1029  */
1030 template <unsigned int N, class T1=void, class T2=void, class T3=void, class T4=void, class T5=void>
1032 {
1033  /** Type of the CoupledHandle.*/
1034  typedef typename CoupledHandleType<N, T1, T2, T3, T4, T5>::type HandleType;
1035 
1036  /** Type of the CoupledScanOrderIterator.*/
1038  typedef IteratorType type;
1039 };
1040 
1041 /** Alias for \ref vigra::CoupledIteratorType (maybe easier to remember).
1042  */
1043 template <unsigned int N, class T1=void, class T2=void, class T3=void, class T4=void, class T5=void>
1045 : public CoupledIteratorType<N, T1, T2, T3, T4, T5>
1046 {};
1047 
1048 /** Returns a CoupledScanOrderIterator from shape to iterate over coordinates.
1049  */
1050 template <int N>
1053 {
1054  typedef typename CoupledHandleType<N>::type P0;
1055  typedef CoupledScanOrderIterator<N, P0> IteratorType;
1056 
1057  return IteratorType(P0(shape));
1058 }
1059 
1060 /** Returns a CoupledScanOrderIterator to simultaneously iterate over image m1 and its coordinates.
1061  */
1062 template <unsigned int N1, class T1, class S1>
1063 typename CoupledIteratorType<N1, T1>::type
1065 {
1066  typedef typename CoupledHandleType<N1, T1>::type P1;
1067  typedef typename P1::base_type P0;
1068  typedef CoupledScanOrderIterator<P1::dimensions, P1> IteratorType;
1069 
1070  return IteratorType(P1(m1,
1071  P0(m1.shape())));
1072 }
1073 
1074 /** Returns a CoupledScanOrderIterator to simultaneously iterate over images m1, m2 and their coordinates.
1075  */
1076 template <unsigned int N1, class T1, class S1,
1077  unsigned int N2, class T2, class S2>
1078 typename CoupledIteratorType<N1, T1, T2>::type
1080  MultiArrayView<N2, T2, S2> const & m2)
1081 {
1082  typedef typename CoupledHandleType<N1, T1, T2>::type P2;
1083  typedef typename P2::base_type P1;
1084  typedef typename P1::base_type P0;
1085  typedef CoupledScanOrderIterator<P2::dimensions, P2> IteratorType;
1086 
1087  return IteratorType(P2(m2,
1088  P1(m1,
1089  P0(m1.shape()))));
1090 }
1091 
1092 /** Returns a CoupledScanOrderIterator to simultaneously iterate over images m1, m2, m3 and their coordinates.
1093  */
1094 template <unsigned int N1, class T1, class S1,
1095  unsigned int N2, class T2, class S2,
1096  unsigned int N3, class T3, class S3>
1097 typename CoupledIteratorType<N1, T1, T2, T3>::type
1099  MultiArrayView<N2, T2, S2> const & m2,
1100  MultiArrayView<N3, T3, S3> const & m3)
1101 {
1102  typedef typename CoupledHandleType<N1, T1, T2, T3>::type P3;
1103  typedef typename P3::base_type P2;
1104  typedef typename P2::base_type P1;
1105  typedef typename P1::base_type P0;
1106  typedef CoupledScanOrderIterator<P3::dimensions, P3> IteratorType;
1107 
1108  return IteratorType(P3(m3,
1109  P2(m2,
1110  P1(m1,
1111  P0(m1.shape())))));
1112 }
1113 
1114 /** Returns a CoupledScanOrderIterator to simultaneously iterate over images m1, m2, m3, m4 and their coordinates.
1115  */
1116 template <unsigned int N1, class T1, class S1,
1117  unsigned int N2, class T2, class S2,
1118  unsigned int N3, class T3, class S3,
1119  unsigned int N4, class T4, class S4>
1120 typename CoupledIteratorType<N1, T1, T2, T3, T4>::type
1122  MultiArrayView<N2, T2, S2> const & m2,
1123  MultiArrayView<N3, T3, S3> const & m3,
1124  MultiArrayView<N4, T4, S4> const & m4)
1125 {
1126  typedef typename CoupledHandleType<N1, T1, T2, T3, T4>::type P4;
1127  typedef typename P4::base_type P3;
1128  typedef typename P3::base_type P2;
1129  typedef typename P2::base_type P1;
1130  typedef typename P1::base_type P0;
1131  typedef CoupledScanOrderIterator<P4::dimensions, P4> IteratorType;
1132 
1133  return IteratorType(P4(m4,
1134  P3(m3,
1135  P2(m2,
1136  P1(m1,
1137  P0(m1.shape()))))));
1138 }
1139 
1140 /** Returns a CoupledScanOrderIterator to simultaneously iterate over images m1, m2, m3, m4, m5 and their coordinates.
1141  */
1142 template <unsigned int N1, class T1, class S1,
1143  unsigned int N2, class T2, class S2,
1144  unsigned int N3, class T3, class S3,
1145  unsigned int N4, class T4, class S4,
1146  unsigned int N5, class T5, class S5>
1147 typename CoupledIteratorType<N1, T1, T2, T3, T4, T5>::type
1149  MultiArrayView<N2, T2, S2> const & m2,
1150  MultiArrayView<N3, T3, S3> const & m3,
1151  MultiArrayView<N4, T4, S4> const & m4,
1152  MultiArrayView<N5, T5, S5> const & m5)
1153 {
1154  typedef typename CoupledHandleType<N1, T1, T2, T3, T4, T5>::type P5;
1155  typedef typename P5::base_type P4;
1156  typedef typename P4::base_type P3;
1157  typedef typename P3::base_type P2;
1158  typedef typename P2::base_type P1;
1159  typedef typename P1::base_type P0;
1160  typedef CoupledScanOrderIterator<P1::dimensions, P5> IteratorType;
1161 
1162  return IteratorType(P5(m5,
1163  P4(m4,
1164  P3(m3,
1165  P2(m2,
1166  P1(m1,
1167  P0(m1.shape())))))));
1168 }
1169 
1170 //@}
1171 
1172 } // namespace vigra
1173 
1174 namespace std {
1175 
1176 template <unsigned int N, class HANDLES, int DIMENSION>
1177 ostream & operator<<(ostream & o, vigra::CoupledScanOrderIterator<N, HANDLES, DIMENSION> const & i)
1178 {
1179  o << i.point();
1180  return o;
1181 }
1182 
1183 } // namespace std
1184 
1185 #endif /* MULTI_ITERATOR_COUPLED_HXX */
Definition: multi_iterator_coupled.hxx:1031
PromoteTraits< V1, V2 >::Promote dot(RGBValue< V1, RIDX1, GIDX1, BIDX1 > const &r1, RGBValue< V2, RIDX2, GIDX2, BIDX2 > const &r2)
dot product
Definition: rgbvalue.hxx:907
Diff2D operator-(Diff2D const &a, Diff2D const &b)
Definition: diff2d.hxx:711
const difference_type & shape() const
Definition: multi_array.hxx:1551
pointer data() const
Definition: multi_array.hxx:1792
Diff2D operator+(Diff2D const &a, Diff2D const &b)
Definition: diff2d.hxx:739
std::ptrdiff_t MultiArrayIndex
Definition: multi_shape.hxx:55
FFTWComplex< R > & operator-=(FFTWComplex< R > &a, const FFTWComplex< R > &b)
subtract-assignment
Definition: fftw3.hxx:867
CoupledScanOrderIterator< HandleType::dimensions, HandleType > IteratorType
Definition: multi_iterator_coupled.hxx:1037
bool operator<=(FixedPoint< IntBits1, FracBits1 > l, FixedPoint< IntBits2, FracBits2 > r)
less or equal
Definition: fixedpoint.hxx:521
CoupledHandleType< N, T1, T2, T3, T4, T5 >::type HandleType
Definition: multi_iterator_coupled.hxx:1034
FFTWComplex< R > & operator+=(FFTWComplex< R > &a, const FFTWComplex< R > &b)
add-assignment
Definition: fftw3.hxx:859
NumericTraits< V >::Promote prod(TinyVectorBase< V, SIZE, D1, D2 > const &l)
product of the vector&#39;s elements
Definition: tinyvector.hxx:1895
const difference_type & stride() const
Definition: multi_array.hxx:1587
vigra::MultiArrayView< N, T, Stride >::const_reference get(vigra::MultiArrayView< N, T, Stride > const &pmap, typename vigra::MultiArrayView< N, T, Stride >::difference_type const &k)
Read the value at key k in property map pmap (API: boost).
Definition: multi_gridgraph.hxx:2859
bool operator!=(FFTWComplex< R > const &a, const FFTWComplex< R > &b)
not equal
Definition: fftw3.hxx:841
CoupledScanOrderIterator getEndIterator() const
Definition: multi_iterator_coupled.hxx:628
bool operator==(FFTWComplex< R > const &a, const FFTWComplex< R > &b)
equal
Definition: fftw3.hxx:825
Definition: multi_iterator_coupled.hxx:1044
Class for fixed size vectors.This class contains an array of size SIZE of the specified VALUETYPE...
Definition: accessor.hxx:940
Definition: multi_iterator_coupled.hxx:52
bool operator<(FixedPoint< IntBits1, FracBits1 > l, FixedPoint< IntBits2, FracBits2 > r)
less than
Definition: fixedpoint.hxx:512
bool operator>=(FixedPoint< IntBits1, FracBits1 > l, FixedPoint< IntBits2, FracBits2 > r)
greater or equal
Definition: fixedpoint.hxx:539
CoupledIteratorType< N >::type createCoupledIterator(TinyVector< MultiArrayIndex, N > const &shape)
Definition: multi_iterator_coupled.hxx:1052
Base class for, and view to, vigra::MultiArray.
Definition: multi_array.hxx:655
Iterate over multiple images simultaneously in scan order.
Definition: multi_iterator_coupled.hxx:526
bool operator>(FixedPoint< IntBits1, FracBits1 > l, FixedPoint< IntBits2, FracBits2 > r)
greater
Definition: fixedpoint.hxx:530
MultiArrayView()
Definition: multi_array.hxx:780

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de)
Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany

html generated using doxygen and Python
vigra 1.10.0 (Tue Dec 31 2013)