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

multi_iterator_coupled.hxx
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
44namespace vigra {
45
46/** \addtogroup MultiIteratorGroup
47*/
48//@{
49
50/********************************************************/
51/* */
52/* CoupledScanOrderIterator<N> */
53/* */
54/********************************************************/
55
56template <class Iterator>
57class 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
189template <unsigned int N,
190 class HANDLES,
191 int DIMENSION> // NOTE: default template arguments are defined in multi_fwd.hxx
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;
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 */
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;
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
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
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
352template <unsigned int N, class HANDLES, int DIMENSION>
353void CoupledScanOrderIterator<N, HANDLES, DIMENSION>::resetAndIncrement()
354{
355 base_type::reset();
356 this->handles_.template increment<dimension>();
357}
358
359template <unsigned int N, class HANDLES, int DIMENSION>
360void CoupledScanOrderIterator<N, HANDLES, DIMENSION>::resetAndDecrement()
361{
362 base_type::inverseReset();
363 this->handles_.template decrement<dimension>();
364}
365
366template <unsigned int N, class HANDLES>
367class 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
693template <unsigned int TARGET_INDEX,
694 unsigned int N,
695 class HANDLES,
696 int DIM>
697typename CoupledScanOrderIterator<N, HANDLES, DIM>::template Reference<TARGET_INDEX>::type
698get(CoupledScanOrderIterator<N, HANDLES, DIM> & i)
699{
700 return vigra::get<TARGET_INDEX>(*i);
701}
702
703template <unsigned int TARGET_INDEX,
704 unsigned int N,
705 class HANDLES,
706 int DIM>
707typename CoupledScanOrderIterator<N, HANDLES, DIM>::template ConstReference<TARGET_INDEX>::type
708get(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 */
715template <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 */
728template <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 */
735template <int N>
737createCoupledIterator(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 */
747template <unsigned int N1, class T1, class S1>
748typename CoupledIteratorType<N1, T1>::type
749createCoupledIterator(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 */
761template <unsigned int N1, class T1, class S1,
762 unsigned int N2, class T2, class S2>
763typename CoupledIteratorType<N1, T1, T2>::type
764createCoupledIterator(MultiArrayView<N1, T1, S1> const & m1,
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 */
779template <unsigned int N1, class T1, class S1,
780 unsigned int N2, class T2, class S2,
781 unsigned int N3, class T3, class S3>
782typename CoupledIteratorType<N1, T1, T2, T3>::type
783createCoupledIterator(MultiArrayView<N1, T1, S1> const & m1,
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 */
801template <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>
805typename CoupledIteratorType<N1, T1, T2, T3, T4>::type
806createCoupledIterator(MultiArrayView<N1, T1, S1> const & m1,
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 */
827template <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>
832typename CoupledIteratorType<N1, T1, T2, T3, T4, T5>::type
833createCoupledIterator(MultiArrayView<N1, T1, S1> const & m1,
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
855template <unsigned int N, class A, class B>
856CoupledScanOrderIterator<N, typename ZipCoupledHandles<A, B>::type>
857zip(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
871namespace std {
872
873template <unsigned int N, class HANDLES, int DIMENSION>
874ostream & 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 */
Iterate over multiple images simultaneously in scan order.
Definition multi_iterator_coupled.hxx:196
CoupledHandleCast< TARGET_INDEX, value_type >::type::const_reference get() const
CoupledHandleCast< TARGET_INDEX, value_type >::type::reference get()
HANDLES value_type
Definition multi_iterator_coupled.hxx:211
CoupledScanOrderIterator getEndIterator() const
Definition multi_iterator_coupled.hxx:282
TinyVector< MultiArrayIndex, N > type
Definition multi_shape.hxx:272
Class for a single RGB value.
Definition rgbvalue.hxx:128
RGBValue()
Definition rgbvalue.hxx:209
LookupTag< TAG, A >::result_type get(A const &a)
Definition accumulator.hxx:2942
bool operator<=(FixedPoint< IntBits1, FracBits1 > l, FixedPoint< IntBits2, FracBits2 > r)
less or equal
Definition fixedpoint.hxx:521
bool operator>=(FixedPoint< IntBits1, FracBits1 > l, FixedPoint< IntBits2, FracBits2 > r)
greater or equal
Definition fixedpoint.hxx:539
FFTWComplex< R > & operator+=(FFTWComplex< R > &a, const FFTWComplex< R > &b)
add-assignment
Definition fftw3.hxx:859
FFTWComplex< R > & operator-=(FFTWComplex< R > &a, const FFTWComplex< R > &b)
subtract-assignment
Definition fftw3.hxx:867
NumericTraits< V >::Promote prod(TinyVectorBase< V, SIZE, D1, D2 > const &l)
product of the vector's elements
Definition tinyvector.hxx:2097
bool operator>(FixedPoint< IntBits1, FracBits1 > l, FixedPoint< IntBits2, FracBits2 > r)
greater
Definition fixedpoint.hxx:530
std::ptrdiff_t MultiArrayIndex
Definition multi_fwd.hxx:60
bool operator<(FixedPoint< IntBits1, FracBits1 > l, FixedPoint< IntBits2, FracBits2 > r)
less than
Definition fixedpoint.hxx:512
bool operator==(FFTWComplex< R > const &a, const FFTWComplex< R > &b)
equal
Definition fftw3.hxx:825
bool operator!=(FFTWComplex< R > const &a, const FFTWComplex< R > &b)
not equal
Definition fftw3.hxx:841
Definition multi_iterator_coupled.hxx:731
Definition multi_iterator_coupled.hxx:717
CoupledHandleType< N, T1, T2, T3, T4, T5 >::type HandleType
Definition multi_iterator_coupled.hxx:719
CoupledScanOrderIterator< HandleType::dimensions, HandleType > IteratorType
Definition multi_iterator_coupled.hxx:722

© 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