[ 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 "multi_fwd.hxx"
40 #include "multi_shape.hxx"
41 #include "multi_handle.hxx"
42 #include "metaprogramming.hxx"
43 
44 namespace vigra {
45 
46 /** \addtogroup MultiIteratorGroup
47 */
48 //@{
49 
50 /********************************************************/
51 /* */
52 /* CoupledScanOrderIterator<N> */
53 /* */
54 /********************************************************/
55 
56 template <class Iterator>
57 class CoupledDimensionProxy
58 : public Iterator
59 {
60  public:
61  typedef typename Iterator::value_type value_type;
62  typedef typename Iterator::difference_type difference_type;
63  typedef typename Iterator::reference reference;
64  typedef typename Iterator::const_reference const_reference;
65  typedef typename Iterator::pointer pointer;
66  typedef CoupledDimensionProxy iterator;
67  typedef std::random_access_iterator_tag iterator_category;
68 
69  static const int dimension = Iterator::dimension;
70 
71  CoupledDimensionProxy & operator++()
72  {
73  this->incDim(dimension);
74  return *this;
75  }
76 
77  CoupledDimensionProxy operator++(int)
78  {
79  CoupledDimensionProxy ret(*this);
80  this->incDim(dimension);
81  return ret;
82  }
83 
84  CoupledDimensionProxy & operator--()
85  {
86  this->decDim(dimension);
87  return *this;
88  }
89 
90  CoupledDimensionProxy operator--(int)
91  {
92  CoupledDimensionProxy ret(*this);
93  this->decDim(dimension);
94  return ret;
95  }
96 
97  CoupledDimensionProxy & operator+=(MultiArrayIndex d)
98  {
99  this->addDim(dimension, d);
100  return *this;
101  }
102 
103  CoupledDimensionProxy & operator-=(MultiArrayIndex d)
104  {
105  this->addDim(dimension, -d);
106  return *this;
107  }
108 
109  value_type operator[](MultiArrayIndex d) const
110  {
111  return *(CoupledDimensionProxy(*this) += d);
112  }
113 
114  CoupledDimensionProxy & operator=(MultiArrayIndex d)
115  {
116  this->setDim(dimension, d);
117  return *this;
118  }
119 
120  bool operator==(MultiArrayIndex d) const
121  {
122  return this->point(dimension) == d;
123  }
124 
125  bool operator!=(MultiArrayIndex d) const
126  {
127  return this->point(dimension) != d;
128  }
129 
130  bool operator<(MultiArrayIndex d) const
131  {
132  return this->point(dimension) < d;
133  }
134 
135  bool operator<=(MultiArrayIndex d) const
136  {
137  return this->point(dimension) <= d;
138  }
139 
140  bool operator>(MultiArrayIndex d) const
141  {
142  return this->point(dimension) > d;
143  }
144 
145  bool operator>=(MultiArrayIndex d) const
146  {
147  return this->point(dimension) >= d;
148  }
149 };
150 
151 /** \brief Iterate over multiple images simultaneously in scan order.
152 
153  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).
154 
155  Instances of this class are usually constructed by calling createCoupledIterator() .
156 
157  To get the type of a CoupledScanOrderIterator for arrays of a certain dimension and element types use CoupledIteratorType::type.
158 
159  The iterator supports all functions listed in the STL documentation for
160  <a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access Iterators</a>.
161 
162  Example of use:
163  \code
164  using namespace vigra;
165  MultiArray<2, double> image1(Shape2(5, 5));
166  MultiArray<2, double> image2(Shape2(5, 5));
167  // fill image with data ...
168 
169  typedef CoupledIteratorType<2, double, double>::type Iterator; // the type of the CoupledScanOrderIterator
170 
171  Iterator start = createCoupledIterator(image1, image2); // create coupled iterator for simultaneous iteration over image1, image2 and their coordinates
172  Iterator end = start.getEndIterator();
173 
174  for (Iterator it = start; it < end; ++it) {
175  std::cout << "coordinates: " << it.get<0>() << std::endl;
176  std::cout << "image1: " << it.get<1>() << std::endl;
177  std::cout << "image2: " << it.get<2>() << std::endl;
178  }
179 
180  //random access:
181  Iterator::value_type handle = start[15];
182  std::cout << "image1: " << get<1>(handle) << std::endl;
183  \endcode
184 
185  <b>\#include</b> <vigra/multi_iterator_coupled.hxx> <br/>
186  Namespace: vigra
187 */
188 
189 template <unsigned int N,
190  class HANDLES,
191  int DIMENSION> // NOTE: default template arguments are defined in multi_fwd.hxx
192 class CoupledScanOrderIterator
193 #ifndef DOXYGEN // doxygen doesn't understand this inheritance
194 : public CoupledScanOrderIterator<N, HANDLES, DIMENSION-1>
195 #endif
196 {
197  typedef CoupledScanOrderIterator<N, HANDLES, DIMENSION-1> base_type;
198 
199  public:
200  static const int dimension = DIMENSION;
201 
202  typedef MultiArrayIndex difference_type;
203  typedef CoupledScanOrderIterator iterator;
204  typedef std::random_access_iterator_tag iterator_category;
205 
206  typedef typename base_type::value_type value_type;
207 
208 #ifdef DOXYGEN
209  /** The type of the CoupledHandle.
210  */
211  typedef HANDLES value_type;
212 #endif
213 
214  typedef typename base_type::shape_type shape_type;
215  typedef typename base_type::reference reference;
216  typedef typename base_type::const_reference const_reference; // FIXME: do we need both?
217  typedef typename base_type::pointer pointer;
218  typedef CoupledDimensionProxy<iterator> dimension_proxy;
219 
220  explicit CoupledScanOrderIterator(value_type const & handles = value_type())
221  : base_type(handles)
222  {}
223 
224  CoupledScanOrderIterator & operator++()
225  {
226  base_type::operator++();
227  if(this->point()[dimension-1] == this->shape()[dimension-1])
228  {
229  resetAndIncrement();
230  }
231  return *this;
232  }
233 
234  CoupledScanOrderIterator operator++(int)
235  {
236  CoupledScanOrderIterator res(*this);
237  ++*this;
238  return res;
239  }
240 
241  CoupledScanOrderIterator & operator+=(MultiArrayIndex i)
242  {
243  base_type::operator+=(i);
244  return *this;
245  }
246 
247  CoupledScanOrderIterator & operator+=(const shape_type &coordOffset)
248  {
249  base_type::operator+=(coordOffset);
250  return *this;
251  }
252 
253  CoupledScanOrderIterator & operator--()
254  {
255  base_type::operator--();
256  if(this->point()[dimension-1] == -1)
257  {
258  resetAndDecrement();
259  }
260  return *this;
261  }
262 
263  CoupledScanOrderIterator operator--(int)
264  {
265  CoupledScanOrderIterator res(*this);
266  --*this;
267  return res;
268  }
269 
270  CoupledScanOrderIterator & operator-=(MultiArrayIndex i)
271  {
272  return operator+=(-i);
273  }
274 
275  CoupledScanOrderIterator & operator-=(const shape_type &coordOffset)
276  {
277  return operator+=(-coordOffset);
278  }
279 
280  /** Returns CoupledScanOrderIterator pointing beyond the last element.
281  */
283  {
284  return operator+(prod(this->shape()) - this->scanOrderIndex());
285  }
286 
287  CoupledScanOrderIterator operator+(MultiArrayIndex d) const
288  {
289  return CoupledScanOrderIterator(*this) += d;
290  }
291 
292  CoupledScanOrderIterator operator-(MultiArrayIndex d) const
293  {
294  return CoupledScanOrderIterator(*this) -= d;
295  }
296 
297  CoupledScanOrderIterator operator+(const shape_type &coordOffset) const
298  {
299  return CoupledScanOrderIterator(*this) += coordOffset;
300  }
301 
302  CoupledScanOrderIterator operator-(const shape_type &coordOffset) const
303  {
304  return CoupledScanOrderIterator(*this) -= coordOffset;
305  }
306 
307  MultiArrayIndex operator-(CoupledScanOrderIterator const & r) const
308  {
309  return base_type::operator-(r);
310  }
311 
312  CoupledScanOrderIterator &
313  restrictToSubarray(shape_type const & start, shape_type const & end)
314  {
315  base_type::restrictToSubarray(start, end);
316  return *this;
317  }
318 
319 #ifdef DOXYGEN
320 
321  /** Returns reference to the element in the band with index TARGET_INDEX.
322  */
323  template<unsigned int TARGET_INDEX>
324  typename CoupledHandleCast<TARGET_INDEX, value_type>::type::reference
325  get();
326 
327  /** Returns constant reference to the element in the band with index TARGET_INDEX.
328  */
329  template<unsigned int TARGET_INDEX>
330  typename CoupledHandleCast<TARGET_INDEX, value_type>::type::const_reference
331  get() const;
332 
333 #endif
334 
335  protected:
336  // placing these functions out-of-line prevents MSVC
337  // from stupid optimizations
338  void resetAndIncrement();
339  void resetAndDecrement();
340 
341  void reset()
342  {
343  this->handles_.template decrement<dimension>(this->shape()[dimension]);
344  }
345 
346  void inverseReset()
347  {
348  this->handles_.template increment<dimension>(this->shape()[dimension]);
349  }
350 };
351 
352 template <unsigned int N, class HANDLES, int DIMENSION>
353 void CoupledScanOrderIterator<N, HANDLES, DIMENSION>::resetAndIncrement()
354 {
355  base_type::reset();
356  this->handles_.template increment<dimension>();
357 }
358 
359 template <unsigned int N, class HANDLES, int DIMENSION>
360 void CoupledScanOrderIterator<N, HANDLES, DIMENSION>::resetAndDecrement()
361 {
362  base_type::inverseReset();
363  this->handles_.template decrement<dimension>();
364 }
365 
366 template <unsigned int N, class HANDLES>
367 class CoupledScanOrderIterator<N, HANDLES, 0>
368 {
369  public:
370 
371  static const int dimension = 0;
372 
373  typedef CoupledScanOrderIterator<N, HANDLES, 0> self_type;
374  typedef HANDLES value_type;
375  typedef MultiArrayIndex difference_type;
376  typedef value_type & reference;
377  typedef value_type const & const_reference;
378  typedef value_type * pointer;
379  typedef typename MultiArrayShape<N>::type shape_type;
380  typedef CoupledScanOrderIterator iterator;
381  typedef std::random_access_iterator_tag iterator_category;
382  typedef CoupledDimensionProxy<iterator> dimension_proxy;
383 
384  template <unsigned int TARGET_INDEX>
385  struct Reference
386  {
387  typedef typename CoupledHandleCast<TARGET_INDEX, HANDLES>::reference type;
388  };
389 
390  template <unsigned int TARGET_INDEX>
391  struct ConstReference
392  {
393  typedef typename CoupledHandleCast<TARGET_INDEX, HANDLES>::const_reference type;
394  };
395 
396  explicit CoupledScanOrderIterator(value_type const & handles = value_type())
397  : handles_(handles),
398  strides_(detail::defaultStride(handles_.shape()))
399  {}
400 
401  template <unsigned int DIM>
402  typename CoupledScanOrderIterator<N, HANDLES, DIM>::dimension_proxy &
403  dim()
404  {
405  typedef CoupledScanOrderIterator<N, HANDLES, DIM> Iter;
406  typedef typename Iter::dimension_proxy Proxy;
407  return static_cast<Proxy &>(static_cast<Iter &>(*this));
408  }
409 
410  template <unsigned int DIM>
411  typename CoupledScanOrderIterator<N, HANDLES, DIM>::dimension_proxy const &
412  dim() const
413  {
414  typedef CoupledScanOrderIterator<N, HANDLES, DIM> Iter;
415  typedef typename Iter::dimension_proxy Proxy;
416  return static_cast<Proxy const &>(static_cast<Iter const &>(*this));
417  }
418 
419  void incDim(int dim)
420  {
421  handles_.incDim(dim);
422  handles_.incrementIndex(strides_[dim]);
423  }
424 
425  void decDim(int dim)
426  {
427  handles_.decDim(dim);
428  handles_.decrementIndex(strides_[dim]);
429  }
430 
431  void addDim(int dim, MultiArrayIndex d)
432  {
433  handles_.addDim(dim, d);
434  handles_.incrementIndex(d*strides_[dim]);
435  }
436 
437  void setDim(int dim, MultiArrayIndex d)
438  {
439  d -= point(dim);
440  handles_.addDim(dim, d);
441  handles_.incrementIndex(d*strides_[dim]);
442  }
443 
444  void resetDim(int dim)
445  {
446  MultiArrayIndex d = -point(dim);
447  handles_.addDim(dim, d);
448  handles_.incrementIndex(d*strides_[dim]);
449  }
450 
451  CoupledScanOrderIterator & operator++()
452  {
453  handles_.template increment<dimension>();
454  handles_.incrementIndex();
455  return *this;
456  }
457 
458  CoupledScanOrderIterator operator++(int)
459  {
460  CoupledScanOrderIterator res(*this);
461  ++*this;
462  return res;
463  }
464 
465  CoupledScanOrderIterator & operator+=(MultiArrayIndex i)
466  {
467  // FIXME: this looks very expensive
468  shape_type coordOffset;
469  detail::ScanOrderToCoordinate<N>::exec(i+scanOrderIndex(), shape(), coordOffset);
470  coordOffset -= point();
471  handles_.add(coordOffset);
472  handles_.scanOrderIndex_ += i;
473  return *this;
474  }
475 
476  CoupledScanOrderIterator & operator+=(const shape_type &coordOffset)
477  {
478  handles_.add(coordOffset);
479  handles_.scanOrderIndex_ += detail::CoordinateToScanOrder<N>::exec(shape(), coordOffset);
480  return *this;
481  }
482 
483  CoupledScanOrderIterator & operator--()
484  {
485  handles_.template decrement<dimension>();
486  handles_.decrementIndex();
487  return *this;
488  }
489 
490  CoupledScanOrderIterator operator--(int)
491  {
492  CoupledScanOrderIterator res(*this);
493  --this;
494  return res;
495  }
496 
497  CoupledScanOrderIterator & operator-=(MultiArrayIndex i)
498  {
499  return operator+=(-i);
500  }
501 
502  CoupledScanOrderIterator & operator-=(const shape_type &coordOffset)
503  {
504  return operator+=(-coordOffset);
505  }
506 
507  value_type operator[](MultiArrayIndex i) const
508  {
509  return *(CoupledScanOrderIterator(*this) += i);
510  }
511 
512  value_type operator[](const shape_type& coordOffset) const
513  {
514  return *(CoupledScanOrderIterator(*this) += coordOffset);
515  }
516 
517  CoupledScanOrderIterator
518  operator+(MultiArrayIndex d) const
519  {
520  return CoupledScanOrderIterator(*this) += d;
521  }
522 
523  CoupledScanOrderIterator
524  operator-(MultiArrayIndex d) const
525  {
526  return CoupledScanOrderIterator(*this) -= d;
527  }
528 
529  CoupledScanOrderIterator operator+(const shape_type &coordOffset) const
530  {
531  return CoupledScanOrderIterator(*this) += coordOffset;
532  }
533 
534  CoupledScanOrderIterator operator-(const shape_type &coordOffset) const
535  {
536  return CoupledScanOrderIterator(*this) -= coordOffset;
537  }
538 
540  operator-(CoupledScanOrderIterator const & r) const
541  {
542  return scanOrderIndex() - r.scanOrderIndex();
543  }
544 
545  bool operator==(CoupledScanOrderIterator const & r) const
546  {
547  return scanOrderIndex() == r.scanOrderIndex();
548  }
549 
550  bool operator!=(CoupledScanOrderIterator const & r) const
551  {
552  return scanOrderIndex() != r.scanOrderIndex();
553  }
554 
555  bool operator<(CoupledScanOrderIterator const & r) const
556  {
557  return scanOrderIndex() < r.scanOrderIndex();
558  }
559 
560  bool operator<=(CoupledScanOrderIterator const & r) const
561  {
562  return scanOrderIndex() <= r.scanOrderIndex();
563  }
564 
565  bool operator>(CoupledScanOrderIterator const & r) const
566  {
567  return scanOrderIndex() > r.scanOrderIndex();
568  }
569 
570  bool operator>=(CoupledScanOrderIterator const & r) const
571  {
572  return scanOrderIndex() >= r.scanOrderIndex();
573  }
574 
575  bool isValid() const
576  {
577  return handles_.scanOrderIndex() < prod(shape());
578  }
579 
580  bool atEnd() const
581  {
582  return handles_.scanOrderIndex() >= prod(shape());
583  }
584 
585  MultiArrayIndex scanOrderIndex() const
586  {
587  return handles_.scanOrderIndex();
588  }
589 
590  shape_type const & coord() const
591  {
592  return handles_.point();
593  }
594 
595  MultiArrayIndex coord(unsigned int dim) const
596  {
597  return coord()[dim];
598  }
599 
600  shape_type const & point() const
601  {
602  return handles_.point();
603  }
604 
605  MultiArrayIndex point(unsigned int dim) const
606  {
607  return point()[dim];
608  }
609 
610  shape_type const & shape() const
611  {
612  return handles_.shape();
613  }
614 
615  MultiArrayIndex shape(unsigned int dim) const
616  {
617  return handles_.shape()[dim];
618  }
619 
620  reference operator*()
621  {
622  return handles_;
623  }
624 
625  const_reference operator*() const
626  {
627  return handles_;
628  }
629 
630  CoupledScanOrderIterator &
631  restrictToSubarray(shape_type const & start, shape_type const & end)
632  {
633  operator+=(-point());
634  handles_.restrictToSubarray(start, end);
635  strides_ = detail::defaultStride(shape());
636  return *this;
637  }
638 
639  CoupledScanOrderIterator getEndIterator() const
640  {
641  return operator+(prod(shape())-scanOrderIndex());
642  }
643 
644  bool atBorder() const
645  {
646  return (handles_.borderType() != 0);
647  }
648 
649  unsigned int borderType() const
650  {
651  return handles_.borderType();
652  }
653 
654  template<unsigned int TARGET_INDEX>
655  typename Reference<TARGET_INDEX>::type
656  get()
657  {
658  return vigra::get<TARGET_INDEX>(handles_);
659  }
660 
661  template<unsigned int TARGET_INDEX>
662  typename ConstReference<TARGET_INDEX>::type
663  get() const
664  {
665  return vigra::get<TARGET_INDEX>(handles_);
666  }
667 
668  reference handles()
669  {
670  return handles_;
671  }
672 
673  const_reference handles() const
674  {
675  return handles_;
676  }
677 
678  protected:
679  void reset()
680  {
681  handles_.template decrement<dimension>(shape()[dimension]);
682  }
683 
684  void inverseReset()
685  {
686  handles_.template increment<dimension>(shape()[dimension]);
687  }
688 
689  value_type handles_;
690  shape_type strides_;
691 };
692 
693 template <unsigned int TARGET_INDEX,
694  unsigned int N,
695  class HANDLES,
696  int DIM>
697 typename CoupledScanOrderIterator<N, HANDLES, DIM>::template Reference<TARGET_INDEX>::type
698 get(CoupledScanOrderIterator<N, HANDLES, DIM> & i)
699 {
700  return vigra::get<TARGET_INDEX>(*i);
701 }
702 
703 template <unsigned int TARGET_INDEX,
704  unsigned int N,
705  class HANDLES,
706  int DIM>
707 typename CoupledScanOrderIterator<N, HANDLES, DIM>::template ConstReference<TARGET_INDEX>::type
708 get(CoupledScanOrderIterator<N, HANDLES, DIM> const & i)
709 {
710  return vigra::get<TARGET_INDEX>(*i);
711 }
712 
713 /** 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.
714  */
715 template <unsigned int N, class T1=void, class T2=void, class T3=void, class T4=void, class T5=void>
717 {
718  /** Type of the CoupledHandle.*/
719  typedef typename CoupledHandleType<N, T1, T2, T3, T4, T5>::type HandleType;
720 
721  /** Type of the CoupledScanOrderIterator.*/
723  typedef IteratorType type;
724 };
725 
726 /** Alias for \ref vigra::CoupledIteratorType (maybe easier to remember).
727  */
728 template <unsigned int N, class T1=void, class T2=void, class T3=void, class T4=void, class T5=void>
730 : public CoupledIteratorType<N, T1, T2, T3, T4, T5>
731 {};
732 
733 /** Returns a CoupledScanOrderIterator from shape to iterate over coordinates.
734  */
735 template <int N>
737 createCoupledIterator(TinyVector<MultiArrayIndex, N> const & shape)
738 {
739  typedef typename CoupledHandleType<N>::type P0;
740  typedef CoupledScanOrderIterator<N, P0> IteratorType;
741 
742  return IteratorType(P0(shape));
743 }
744 
745 /** Returns a CoupledScanOrderIterator to simultaneously iterate over image m1 and its coordinates.
746  */
747 template <unsigned int N1, class T1, class S1>
748 typename CoupledIteratorType<N1, T1>::type
749 createCoupledIterator(MultiArrayView<N1, T1, S1> const & m1)
750 {
751  typedef typename CoupledHandleType<N1, T1>::type P1;
752  typedef typename P1::base_type P0;
754 
755  return IteratorType(P1(m1,
756  P0(m1.shape())));
757 }
758 
759 /** Returns a CoupledScanOrderIterator to simultaneously iterate over images m1, m2 and their coordinates.
760  */
761 template <unsigned int N1, class T1, class S1,
762  unsigned int N2, class T2, class S2>
763 typename CoupledIteratorType<N1, T1, T2>::type
764 createCoupledIterator(MultiArrayView<N1, T1, S1> const & m1,
765  MultiArrayView<N2, T2, S2> const & m2)
766 {
767  typedef typename CoupledHandleType<N1, T1, T2>::type P2;
768  typedef typename P2::base_type P1;
769  typedef typename P1::base_type P0;
771 
772  return IteratorType(P2(m2,
773  P1(m1,
774  P0(m1.shape()))));
775 }
776 
777 /** Returns a CoupledScanOrderIterator to simultaneously iterate over images m1, m2, m3 and their coordinates.
778  */
779 template <unsigned int N1, class T1, class S1,
780  unsigned int N2, class T2, class S2,
781  unsigned int N3, class T3, class S3>
782 typename CoupledIteratorType<N1, T1, T2, T3>::type
783 createCoupledIterator(MultiArrayView<N1, T1, S1> const & m1,
784  MultiArrayView<N2, T2, S2> const & m2,
785  MultiArrayView<N3, T3, S3> const & m3)
786 {
787  typedef typename CoupledHandleType<N1, T1, T2, T3>::type P3;
788  typedef typename P3::base_type P2;
789  typedef typename P2::base_type P1;
790  typedef typename P1::base_type P0;
792 
793  return IteratorType(P3(m3,
794  P2(m2,
795  P1(m1,
796  P0(m1.shape())))));
797 }
798 
799 /** Returns a CoupledScanOrderIterator to simultaneously iterate over images m1, m2, m3, m4 and their coordinates.
800  */
801 template <unsigned int N1, class T1, class S1,
802  unsigned int N2, class T2, class S2,
803  unsigned int N3, class T3, class S3,
804  unsigned int N4, class T4, class S4>
805 typename CoupledIteratorType<N1, T1, T2, T3, T4>::type
806 createCoupledIterator(MultiArrayView<N1, T1, S1> const & m1,
807  MultiArrayView<N2, T2, S2> const & m2,
808  MultiArrayView<N3, T3, S3> const & m3,
809  MultiArrayView<N4, T4, S4> const & m4)
810 {
811  typedef typename CoupledHandleType<N1, T1, T2, T3, T4>::type P4;
812  typedef typename P4::base_type P3;
813  typedef typename P3::base_type P2;
814  typedef typename P2::base_type P1;
815  typedef typename P1::base_type P0;
817 
818  return IteratorType(P4(m4,
819  P3(m3,
820  P2(m2,
821  P1(m1,
822  P0(m1.shape()))))));
823 }
824 
825 /** Returns a CoupledScanOrderIterator to simultaneously iterate over images m1, m2, m3, m4, m5 and their coordinates.
826  */
827 template <unsigned int N1, class T1, class S1,
828  unsigned int N2, class T2, class S2,
829  unsigned int N3, class T3, class S3,
830  unsigned int N4, class T4, class S4,
831  unsigned int N5, class T5, class S5>
832 typename CoupledIteratorType<N1, T1, T2, T3, T4, T5>::type
833 createCoupledIterator(MultiArrayView<N1, T1, S1> const & m1,
834  MultiArrayView<N2, T2, S2> const & m2,
835  MultiArrayView<N3, T3, S3> const & m3,
836  MultiArrayView<N4, T4, S4> const & m4,
837  MultiArrayView<N5, T5, S5> const & m5)
838 {
839  typedef typename CoupledHandleType<N1, T1, T2, T3, T4, T5>::type P5;
840  typedef typename P5::base_type P4;
841  typedef typename P4::base_type P3;
842  typedef typename P3::base_type P2;
843  typedef typename P2::base_type P1;
844  typedef typename P1::base_type P0;
846 
847  return IteratorType(P5(m5,
848  P4(m4,
849  P3(m3,
850  P2(m2,
851  P1(m1,
852  P0(m1.shape())))))));
853 }
854 
855 template <unsigned int N, class A, class B>
856 CoupledScanOrderIterator<N, typename ZipCoupledHandles<A, B>::type>
857 zip(CoupledScanOrderIterator<N, A> const & a, CoupledScanOrderIterator<N, B> const & b)
858 {
859  vigra_precondition(a.shape() == b.shape() && a.scanOrderIndex() == b.scanOrderIndex(),
860  "zip(CoupledScanOrderIterator): iterators must have identical shape and position.");
861 
862  typedef typename ZipCoupledHandles<A, B>::type Handle;
863  typedef CoupledScanOrderIterator<N, Handle> IteratorType;
864  return IteratorType(ZipCoupledHandles<A, B>::construct(*a, *b));
865 }
866 
867 //@}
868 
869 } // namespace vigra
870 
871 namespace std {
872 
873 template <unsigned int N, class HANDLES, int DIMENSION>
874 ostream & operator<<(ostream & o, vigra::CoupledScanOrderIterator<N, HANDLES, DIMENSION> const & i)
875 {
876  o << i.point();
877  return o;
878 }
879 
880 } // namespace std
881 
882 #endif /* MULTI_ITERATOR_COUPLED_HXX */
Definition: multi_iterator_coupled.hxx:716
const difference_type & shape() const
Definition: multi_array.hxx:1648
std::ptrdiff_t MultiArrayIndex
Definition: multi_fwd.hxx:60
FFTWComplex< R > & operator-=(FFTWComplex< R > &a, const FFTWComplex< R > &b)
subtract-assignment
Definition: fftw3.hxx:867
HANDLES value_type
Definition: multi_iterator_coupled.hxx:211
CoupledScanOrderIterator< HandleType::dimensions, HandleType > IteratorType
Definition: multi_iterator_coupled.hxx:722
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:719
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's elements
Definition: tinyvector.hxx:2097
bool operator!=(FFTWComplex< R > const &a, const FFTWComplex< R > &b)
not equal
Definition: fftw3.hxx:841
CoupledScanOrderIterator getEndIterator() const
Definition: multi_iterator_coupled.hxx:282
bool operator==(FFTWComplex< R > const &a, const FFTWComplex< R > &b)
equal
Definition: fftw3.hxx:825
Definition: multi_iterator_coupled.hxx:729
Class for fixed size vectors.This class contains an array of size SIZE of the specified VALUETYPE...
Definition: accessor.hxx:940
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
Base class for, and view to, vigra::MultiArray.
Definition: multi_array.hxx:704
Iterate over multiple images simultaneously in scan order.
Definition: multi_fwd.hxx:167
bool operator>(FixedPoint< IntBits1, FracBits1 > l, FixedPoint< IntBits2, FracBits2 > r)
greater
Definition: fixedpoint.hxx:530

© 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.11.1 (Fri May 19 2017)