vigra - vigra/multi_iterator_coupled.hxx Source File

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

vigra/multi_iterator_coupled.hxx |

    00001 /************************************************************************/
    00002 /*                                                                      */
    00003 /*     Copyright 2011-2012 by Stefan Schmidt and Ullrich Koethe         */
    00004 /*                                                                      */
    00005 /*    This file is part of the VIGRA computer vision library.           */
    00006 /*    The VIGRA Website is                                              */
    00007 /*        http://hci.iwr.uni-heidelberg.de/vigra/                       */
    00008 /*    Please direct questions, bug reports, and contributions to        */
    00009 /*        ullrich.koethe@iwr.uni-heidelberg.de    or                    */
    00010 /*        vigra@informatik.uni-hamburg.de                               */
    00011 /*                                                                      */
    00012 /*    Permission is hereby granted, free of charge, to any person       */
    00013 /*    obtaining a copy of this software and associated documentation    */
    00014 /*    files (the "Software"), to deal in the Software without           */
    00015 /*    restriction, including without limitation the rights to use,      */
    00016 /*    copy, modify, merge, publish, distribute, sublicense, and/or      */
    00017 /*    sell copies of the Software, and to permit persons to whom the    */
    00018 /*    Software is furnished to do so, subject to the following          */
    00019 /*    conditions:                                                       */
    00020 /*                                                                      */
    00021 /*    The above copyright notice and this permission notice shall be    */
    00022 /*    included in all copies or substantial portions of the             */
    00023 /*    Software.                                                         */
    00024 /*                                                                      */
    00025 /*    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND    */
    00026 /*    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES   */
    00027 /*    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND          */
    00028 /*    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT       */
    00029 /*    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,      */
    00030 /*    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING      */
    00031 /*    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR     */
    00032 /*    OTHER DEALINGS IN THE SOFTWARE.                                   */
    00033 /*                                                                      */
    00034 /************************************************************************/
    00035
    00036 #ifndef MULTI_ITERATOR_COUPLED_HXX_
    00037 #define MULTI_ITERATOR_COUPLED_HXX_
    00038
    00039 #include "metaprogramming.hxx"
    00040 #include "multi_iterator.hxx"
    00041
    00042 namespace vigra {
    00043
    00044 /** \addtogroup MultiIteratorGroup
    00045 */
    00046 //@{
    00047
    00048
    00049     // FIXME: this should go into its separate header file,
    00050     //        together with the calculation of neighborhod offsets for GridGraph
    00051 template <unsigned int N, unsigned int DIMENSION=N-1>
    00052 struct NeighborhoodTypeImpl
    00053 {
    00054     typedef typename MultiArrayShape<N>::type shape_type;
    00055
    00056     static unsigned int exec(shape_type const & point, shape_type const & shape)
    00057     {
    00058         unsigned int res = NeighborhoodTypeImpl<N, DIMENSION-1>::exec(point, shape);
    00059         if(point[DIMENSION] == 0)
    00060             res |= (1 << 2*DIMENSION);
    00061         if(point[DIMENSION] == shape[DIMENSION]-1)
    00062             res |= (2 << 2*DIMENSION);
    00063         return res;
    00064     }
    00065 };
    00066
    00067 template <unsigned int N>
    00068 struct NeighborhoodTypeImpl<N, 0>
    00069 {
    00070     typedef typename MultiArrayShape<N>::type shape_type;
    00071     static const unsigned int DIMENSION = 0;
    00072
    00073     static unsigned int exec(shape_type const & point, shape_type const & shape)
    00074     {
    00075         unsigned int res = 0;
    00076         if(point[DIMENSION] == 0)
    00077             res |= (1 << 2*DIMENSION);
    00078         if(point[DIMENSION] == shape[DIMENSION]-1)
    00079             res |= (2 << 2*DIMENSION);
    00080         return res;
    00081     }
    00082 };
    00083
    00084   /**
    00085      Handle class, used by CoupledScanOrderIterator as the value type to simultaneously itearate over multiple images.
    00086   */
    00087 template <class T, class NEXT>
    00088 class CoupledHandle
    00089 : public NEXT
    00090 {
    00091 public:
    00092     typedef NEXT                            base_type;
    00093     typedef CoupledHandle<T, NEXT>          self_type;
    00094
    00095     static const int index =                NEXT::index + 1;    // index of this member of the chain
    00096     static const unsigned int dimensions =  NEXT::dimensions;
    00097
    00098     typedef T                               value_type;
    00099     typedef T *                             pointer;
    00100     typedef T const *                       const_pointer;
    00101     typedef T &                             reference;
    00102     typedef T const &                       const_reference;
    00103     typedef typename base_type::shape_type  shape_type;
    00104
    00105     CoupledHandle()
    00106     : base_type(),
    00107       pointer_(),
    00108       strides_()
    00109     {}
    00110
    00111     CoupledHandle(const_pointer p, shape_type const & strides, NEXT const & next)
    00112     : base_type(next),
    00113       pointer_(const_cast<pointer>(p)),
    00114       strides_(strides)
    00115     {}
    00116
    00117     template <class Stride>
    00118     CoupledHandle(MultiArrayView<dimensions, T, Stride> const & v, NEXT const & next)
    00119     : base_type(next),
    00120       pointer_(const_cast<pointer>(v.data())),
    00121       strides_(v.stride())
    00122     {
    00123         vigra_precondition(v.shape() == this->shape(), "createCoupledIterator(): shape mismatch.");
    00124     }
    00125
    00126     template<int DIMENSION>
    00127     inline void increment()
    00128     {
    00129         pointer_ += strides_[DIMENSION];
    00130         base_type::template increment<DIMENSION>();
    00131     }
    00132
    00133     template<int DIMENSION>
    00134     inline void decrement()
    00135     {
    00136         pointer_ -= strides_[DIMENSION];
    00137         base_type::template decrement<DIMENSION>();
    00138     }
    00139
    00140     // TODO: test if making the above a default case of the this hurts performance
    00141     template<int DIMENSION>
    00142     inline void increment(MultiArrayIndex offset)
    00143     {
    00144         pointer_ += offset*strides_[DIMENSION];
    00145         base_type::template increment<DIMENSION>(offset);
    00146     }
    00147
    00148     template<int DIMENSION>
    00149     inline void decrement(MultiArrayIndex offset)
    00150     {
    00151         pointer_ -= offset*strides_[DIMENSION];
    00152         base_type::template decrement<DIMENSION>(offset);
    00153     }
    00154
    00155     void restrictToSubarray(shape_type const & start, shape_type const & end)
    00156     {
    00157         pointer_ += dot(start, strides_);
    00158         base_type::restrictToSubarray(start, end);
    00159     }
    00160
    00161     // ptr access
    00162     reference operator*()
    00163     {
    00164         return *pointer_;
    00165     }
    00166
    00167     const_reference operator*() const
    00168     {
    00169         return *pointer_;
    00170     }
    00171
    00172     pointer operator->()
    00173     {
    00174         return pointer_;
    00175     }
    00176
    00177     const_pointer operator->() const
    00178     {
    00179         return pointer_;
    00180     }
    00181
    00182     pointer ptr()
    00183     {
    00184         return pointer_;
    00185     }
    00186
    00187     const_pointer ptr() const
    00188     {
    00189         return pointer_;
    00190     }
    00191
    00192     shape_type const & strides() const
    00193     {
    00194         return strides_;
    00195     }
    00196
    00197     pointer pointer_;
    00198     shape_type strides_;
    00199 };
    00200
    00201
    00202 template <int N>
    00203 class CoupledHandle<TinyVector<MultiArrayIndex, N>, void>
    00204 {
    00205 public:
    00206     static const int index = 0;                   // index of this member of the chain
    00207     static const unsigned int dimensions = N;
    00208
    00209     typedef typename MultiArrayShape<N>::type   value_type;
    00210     typedef value_type const *                  pointer;
    00211     typedef value_type const *                  const_pointer;
    00212     typedef value_type const &                  reference;
    00213     typedef value_type const &                  const_reference;
    00214     typedef value_type                          shape_type;
    00215     typedef CoupledHandle<value_type, void>     self_type;
    00216
    00217     CoupledHandle()
    00218     : point_(),
    00219       shape_(),
    00220       scanOrderIndex_()
    00221     {}
    00222
    00223     CoupledHandle(value_type const & shape)
    00224     : point_(),
    00225       shape_(shape),
    00226       scanOrderIndex_()
    00227     {}
    00228
    00229     CoupledHandle(typename MultiArrayShape<N+1>::type const & shape)
    00230     : point_(),
    00231       shape_(shape.begin()),
    00232       scanOrderIndex_()
    00233     {}
    00234
    00235     template<int DIMENSION>
    00236     inline void increment()
    00237     {
    00238         ++point_[DIMENSION];
    00239     }
    00240
    00241     template<int DIMENSION>
    00242     inline void decrement()
    00243     {
    00244         --point_[DIMENSION];
    00245     }
    00246
    00247     // TODO: test if making the above a default case of the this hurts performance
    00248     template<int DIMENSION>
    00249     inline void increment(MultiArrayIndex offset)
    00250     {
    00251         point_[DIMENSION] += offset;
    00252     }
    00253
    00254     template<int DIMENSION>
    00255     inline void decrement(MultiArrayIndex offset)
    00256     {
    00257         point_[DIMENSION] -= offset;
    00258     }
    00259
    00260     void restrictToSubarray(shape_type const & start, shape_type const & end)
    00261     {
    00262         point_ = shape_type();
    00263         shape_ = end - start;
    00264         scanOrderIndex_ = 0;
    00265     }
    00266
    00267     inline void incrementIndex()
    00268     {
    00269         ++scanOrderIndex_;
    00270     }
    00271
    00272     inline void decrementIndex()
    00273     {
    00274         --scanOrderIndex_;
    00275     }
    00276
    00277     inline void incrementIndex(MultiArrayIndex offset)
    00278     {
    00279         scanOrderIndex_ += offset;
    00280     }
    00281
    00282     inline void decrementIndex(MultiArrayIndex offset)
    00283     {
    00284         scanOrderIndex_ -= offset;
    00285     }
    00286
    00287     // access
    00288     MultiArrayIndex scanOrderIndex() const
    00289     {
    00290         return scanOrderIndex_;
    00291     }
    00292
    00293     // access
    00294     const_reference point() const
    00295     {
    00296         return point_;
    00297     }
    00298
    00299     // access
    00300     const_reference shape() const
    00301     {
    00302         return shape_;
    00303     }
    00304
    00305     const_reference operator*() const
    00306     {
    00307         return point_;
    00308     }
    00309
    00310     const_pointer operator->() const
    00311     {
    00312         return &point_;
    00313     }
    00314
    00315     const_pointer ptr() const
    00316     {
    00317         return &point_;
    00318     }
    00319
    00320     unsigned int neighborhoodType() const
    00321     {
    00322         return NeighborhoodTypeImpl<N>::exec(point_, shape_);
    00323     }
    00324
    00325     value_type point_, shape_;
    00326     MultiArrayIndex scanOrderIndex_;
    00327 };
    00328
    00329 template <class T>
    00330 struct Multiband;
    00331
    00332 template <unsigned int N, class T, class StrideTag>
    00333 class MultiArrayView<N, Multiband<T>, StrideTag>
    00334 : public MultiArrayView<N, T, StrideTag>
    00335 {
    00336   public:
    00337     MultiArrayView(MultiArrayView<N, T, StrideTag> const & v)
    00338     : MultiArrayView<N, T, StrideTag>(v)
    00339     {}
    00340 };
    00341
    00342 template <class T, class NEXT>
    00343 class CoupledHandle<Multiband<T>, NEXT>
    00344 : public NEXT
    00345 {
    00346 public:
    00347     typedef NEXT                                  base_type;
    00348     typedef CoupledHandle<Multiband<T>, NEXT>     self_type;
    00349
    00350     static const int index =                      NEXT::index + 1;    // index of this member of the chain
    00351     static const unsigned int dimensions =        NEXT::dimensions;
    00352
    00353     typedef MultiArrayView<1, T, StridedArrayTag> value_type;
    00354     typedef value_type *                          pointer;
    00355     typedef value_type const *                    const_pointer;
    00356     typedef value_type &                          reference;
    00357     typedef value_type const &                    const_reference;
    00358     typedef typename base_type::shape_type        shape_type;
    00359
    00360     CoupledHandle()
    00361     : base_type(),
    00362       view_(),
    00363       strides_()
    00364     {}
    00365
    00366     CoupledHandle(const_reference p, shape_type const & strides, NEXT const & next)
    00367     : base_type(next),
    00368       view_(p),
    00369       strides_(strides)
    00370     {}
    00371
    00372     template <class Stride>
    00373     CoupledHandle(MultiArrayView<dimensions+1, Multiband<T>, Stride> const & v, NEXT const & next)
    00374     : base_type(next),
    00375       view_(v.bindInner(shape_type())),
    00376       strides_(v.bindOuter(0).stride())
    00377     {
    00378         vigra_precondition(v.bindOuter(0).shape() == this->shape(), "createCoupledIterator(): shape mismatch.");
    00379     }
    00380
    00381     template<int DIMENSION>
    00382     inline void increment()
    00383     {
    00384         view_.unsafePtr() += strides_[DIMENSION];
    00385         base_type::template increment<DIMENSION>();
    00386     }
    00387
    00388     template<int DIMENSION>
    00389     inline void decrement()
    00390     {
    00391         view_.unsafePtr() -= strides_[DIMENSION];
    00392         base_type::template decrement<DIMENSION>();
    00393     }
    00394
    00395     // TODO: test if making the above a default case of the this hurts performance
    00396     template<int DIMENSION>
    00397     inline void increment(MultiArrayIndex offset)
    00398     {
    00399         view_.unsafePtr() += offset*strides_[DIMENSION];
    00400         base_type::template increment<DIMENSION>(offset);
    00401     }
    00402
    00403     template<int DIMENSION>
    00404     inline void decrement(MultiArrayIndex offset)
    00405     {
    00406         view_.unsafePtr() -= offset*strides_[DIMENSION];
    00407         base_type::template decrement<DIMENSION>(offset);
    00408     }
    00409
    00410     void restrictToSubarray(shape_type const & start, shape_type const & end)
    00411     {
    00412         view_.unsafePtr() += dot(start, strides_);
    00413         base_type::restrictToSubarray(start, end);
    00414     }
    00415
    00416     // ptr access
    00417     reference operator*()
    00418     {
    00419         return view_;
    00420     }
    00421
    00422     const_reference operator*() const
    00423     {
    00424         return view_;
    00425     }
    00426
    00427     pointer operator->()
    00428     {
    00429         return &view_;
    00430     }
    00431
    00432     const_pointer operator->() const
    00433     {
    00434         return &view_;
    00435     }
    00436
    00437     pointer ptr()
    00438     {
    00439         return &view_;
    00440     }
    00441
    00442     const_pointer ptr() const
    00443     {
    00444         return &view_;
    00445     }
    00446
    00447     shape_type const & strides() const
    00448     {
    00449         return strides_;
    00450     }
    00451
    00452     value_type view_;
    00453     shape_type strides_;
    00454 };
    00455
    00456 template <unsigned TARGET_INDEX>
    00457 struct Error__CoupledHandle_index_out_of_range;
    00458
    00459 namespace detail {
    00460
    00461 template <unsigned TARGET_INDEX, class Handle, bool isValid, unsigned int INDEX=Handle::index>
    00462 struct CoupledHandleCastImpl
    00463 {
    00464     typedef typename CoupledHandleCastImpl<TARGET_INDEX, typename Handle::base_type, isValid>::type type;
    00465 };
    00466
    00467 template <unsigned TARGET_INDEX, class Handle, unsigned int INDEX>
    00468 struct CoupledHandleCastImpl<TARGET_INDEX, Handle, false, INDEX>
    00469 {
    00470     typedef Error__CoupledHandle_index_out_of_range<TARGET_INDEX> type;
    00471 };
    00472
    00473 template <unsigned TARGET_INDEX, class Handle>
    00474 struct CoupledHandleCastImpl<TARGET_INDEX, Handle, true, TARGET_INDEX>
    00475 {
    00476     typedef Handle type;
    00477 };
    00478
    00479 } // namespace detail
    00480
    00481 template <unsigned TARGET_INDEX, class Handle, unsigned int INDEX=Handle::index>
    00482 struct CoupledHandleCast
    00483 : public detail::CoupledHandleCastImpl<TARGET_INDEX, Handle, (TARGET_INDEX <= INDEX), INDEX>
    00484 {};
    00485
    00486 template <unsigned int TARGET_INDEX, class Handle>
    00487 typename CoupledHandleCast<TARGET_INDEX, Handle>::type &
    00488 cast(Handle & handle)
    00489 {
    00490     return handle;
    00491 };
    00492
    00493 template <unsigned int TARGET_INDEX, class Handle>
    00494 typename CoupledHandleCast<TARGET_INDEX, Handle>::type const &
    00495 cast(Handle const & handle)
    00496 {
    00497     return handle;
    00498 };
    00499
    00500   /** Returns reference to the element in the band of the handle with index TARGET_INDEX.
    00501    */
    00502 template <unsigned int TARGET_INDEX, class Handle>
    00503 typename CoupledHandleCast<TARGET_INDEX, Handle>::type::reference
    00504 get(Handle & handle)
    00505 {
    00506     return *cast<TARGET_INDEX>(handle);
    00507 };
    00508
    00509   /** Returns a constant reference to the element in the band of the handle with index TARGET_INDEX.
    00510    */
    00511 template <unsigned int TARGET_INDEX, class Handle>
    00512 typename CoupledHandleCast<TARGET_INDEX, Handle>::type::const_reference
    00513 get(Handle const & handle)
    00514 {
    00515     return *cast<TARGET_INDEX>(handle);
    00516 };
    00517
    00518 /********************************************************/
    00519 /*                                                      */
    00520 /*               CoupledScanOrderIterator<N>            */
    00521 /*                                                      */
    00522 /********************************************************/
    00523
    00524 /** \brief Iterate over multiple images simultaneously in scan order.
    00525
    00526     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).
    00527
    00528     Instances of this class are usually constructed by calling createCoupledIterator() .
    00529
    00530     To get the type of a CoupledScanOrderIterator for arrays of a certain dimension and element types use CoupledIteratorType::type.
    00531
    00532     The iterator supports all functions listed in the STL documentation for
    00533         <a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
    00534 Access Iterators</a>.
    00535
    00536     Example of use:
    00537     \code
    00538     using namespace vigra;
    00539     MultiArray<2, double> image1(Shape2(5, 5));
    00540     MultiArray<2, double> image2(Shape2(5, 5));
    00541     // fill image with data ...
    00542
    00543     typedef CoupledIteratorType<2, double, double>::type Iterator; // the type of the CoupledScanOrderIterator
    00544
    00545     Iterator start = createCoupledIterator(image1, image2); // create coupled iterator for simultaneous iteration over image1, image2 and their coordinates
    00546     Iterator end = start.getEndIterator();
    00547
    00548     for (Iterator it = start; it < end; ++it) {
    00549       std::cout << "coordinates: " << it.get<0>() << std::endl;
    00550       std::cout << "image1: " << it.get<1>() << std::endl;
    00551       std::cout << "image2: " << it.get<2>() << std::endl;
    00552     }
    00553
    00554     //random access:
    00555     Iterator::value_type handle = start[15];
    00556     std::cout << "image1: " << get<1>(handle) << std::endl;
    00557     \endcode
    00558
    00559 <b>\#include</b> <vigra/multi_iterator_coupled.hxx>
    00560
    00561 Namespace: vigra
    00562 */
    00563
    00564 template <unsigned int N,
    00565           class HANDLES,
    00566           int DIMENSION = N-1>
    00567 class CoupledScanOrderIterator
    00568 #ifndef DOXYGEN  // doxygen doesn't understand this inheritance
    00569 : protected CoupledScanOrderIterator<N, HANDLES, DIMENSION-1>
    00570 #endif
    00571 {
    00572     typedef CoupledScanOrderIterator<N, HANDLES, DIMENSION-1> base_type;
    00573     static const int dimension = DIMENSION;
    00574
    00575   public:
    00576
    00577     typedef typename MultiArrayShape<dimension+1>::type        shape_type;
    00578     typedef MultiArrayIndex                   difference_type;
    00579     typedef CoupledScanOrderIterator          iterator;
    00580     typedef std::random_access_iterator_tag   iterator_category;
    00581
    00582     typedef typename base_type::value_type      value_type;
    00583
    00584 #ifdef DOXYGEN
    00585   /** The type of the CoupledHandle.
    00586    */
    00587     typedef HANDLES value_type;
    00588 #endif
    00589
    00590     typedef typename base_type::reference       reference;
    00591     typedef typename base_type::const_reference const_reference; // FIXME: do we need both?
    00592     typedef typename base_type::pointer         pointer;
    00593
    00594     CoupledScanOrderIterator(value_type const & handles = value_type())
    00595     : base_type(handles)
    00596     {}
    00597
    00598     value_type operator[](MultiArrayIndex i) const
    00599     {
    00600         return *(CoupledScanOrderIterator(*this) += i);
    00601     }
    00602
    00603     CoupledScanOrderIterator & operator++()
    00604     {
    00605         base_type::operator++();
    00606         if(this->point()[dimension-1] == this->shape()[dimension-1])
    00607         {
    00608             base_type::reset();
    00609             this->handles_.template increment<dimension>();
    00610         }
    00611         return *this;
    00612     }
    00613
    00614     CoupledScanOrderIterator operator++(int)
    00615     {
    00616         CoupledScanOrderIterator res(*this);
    00617         ++*this;
    00618         return res;
    00619     }
    00620
    00621     CoupledScanOrderIterator & operator+=(MultiArrayIndex i)
    00622     {
    00623         // FIXME: this looks very expensive
    00624         shape_type coordOffset;
    00625         detail::ScanOrderToCoordinate<N>::exec(i+scanOrderIndex(), this->shape(), coordOffset);
    00626         coordOffset -= point();
    00627         moveRelative(coordOffset);
    00628         this->handles_.scanOrderIndex_ += i;
    00629         return *this;
    00630     }
    00631
    00632     CoupledScanOrderIterator & operator+=(const shape_type &coordOffset)
    00633     {
    00634         moveRelative(coordOffset);
    00635         this->handles_.scanOrderIndex_ += detail::CoordinateToScanOrder<N>::exec(this->shape(), coordOffset);
    00636         return *this;
    00637     }
    00638
    00639     CoupledScanOrderIterator & operator--()
    00640     {
    00641         base_type::operator--();
    00642         if(this->point()[dimension-1] == -1)
    00643         {
    00644             base_type::inverseReset();
    00645             this->handles_.template decrement<dimension>();
    00646         }
    00647         return *this;
    00648     }
    00649
    00650     CoupledScanOrderIterator operator--(int)
    00651     {
    00652         CoupledScanOrderIterator res(*this);
    00653         --*this;
    00654         return res;
    00655     }
    00656
    00657     CoupledScanOrderIterator & operator-=(MultiArrayIndex i)
    00658     {
    00659         return operator+=(-i);
    00660     }
    00661
    00662     CoupledScanOrderIterator & operator-=(const shape_type &coordOffset)
    00663     {
    00664         return operator+=(-coordOffset);
    00665     }
    00666
    00667     /** Returns CoupledScanOrderIterator pointing beyond the last element.
    00668     */
    00669     CoupledScanOrderIterator getEndIterator() const
    00670     {
    00671         return operator+(prod(this->shape()));
    00672     }
    00673
    00674     CoupledScanOrderIterator operator+(MultiArrayIndex d) const
    00675     {
    00676         return CoupledScanOrderIterator(*this) += d;
    00677     }
    00678
    00679     CoupledScanOrderIterator operator-(MultiArrayIndex d) const
    00680     {
    00681         return CoupledScanOrderIterator(*this) -= d;
    00682     }
    00683
    00684     CoupledScanOrderIterator operator+(const shape_type &coordOffset) const
    00685     {
    00686         return CoupledScanOrderIterator(*this) += coordOffset;
    00687     }
    00688
    00689     CoupledScanOrderIterator operator-(const shape_type &coordOffset) const
    00690     {
    00691         return CoupledScanOrderIterator(*this) -= coordOffset;
    00692     }
    00693
    00694     MultiArrayIndex operator-(CoupledScanOrderIterator const & r) const
    00695     {
    00696         return base_type::operator-(r);
    00697     }
    00698
    00699     bool operator==(CoupledScanOrderIterator const & r)
    00700     {
    00701         return base_type::operator==(r);
    00702     }
    00703
    00704     bool operator!=(CoupledScanOrderIterator const & r) const
    00705     {
    00706         return base_type::operator!=(r);
    00707     }
    00708
    00709     bool operator<(CoupledScanOrderIterator const & r) const
    00710     {
    00711         return base_type::operator<(r);
    00712     }
    00713
    00714     bool operator<=(CoupledScanOrderIterator const & r) const
    00715     {
    00716         return base_type::operator<=(r);
    00717     }
    00718
    00719     bool operator>(CoupledScanOrderIterator const & r) const
    00720     {
    00721         return base_type::operator>(r);
    00722     }
    00723
    00724     bool operator>=(CoupledScanOrderIterator const & r) const
    00725     {
    00726         return base_type::operator>=(r);
    00727     }
    00728
    00729     using base_type::operator*;
    00730     using base_type::point;
    00731     using base_type::shape;
    00732     using base_type::scanOrderIndex;
    00733     using base_type::atBorder;
    00734     using base_type::neighborhoodType;
    00735     using base_type::get;
    00736
    00737 #ifdef DOXYGEN
    00738
    00739   /** Returns reference to the element in the band with index TARGET_INDEX.
    00740   */
    00741   template<unsigned int TARGET_INDEX>
    00742   typename CoupledHandleCast<TARGET_INDEX, value_type>::type::reference
    00743   get()
    00744   {
    00745     return vigra::get<TARGET_INDEX>(handles_);
    00746   }
    00747
    00748   /** Returns constant reference to the element in the band with index TARGET_INDEX.
    00749   */
    00750   template<unsigned int TARGET_INDEX>
    00751   typename CoupledHandleCast<TARGET_INDEX, value_type>::type::const_reference
    00752   get() const
    00753   {
    00754     return vigra::get<TARGET_INDEX>(handles_);
    00755   }
    00756 #endif
    00757
    00758   protected:
    00759     void reset()
    00760     {
    00761         this->handles_.template decrement<dimension>(this->shape()[dimension]);
    00762     }
    00763
    00764     void inverseReset()
    00765     {
    00766         this->handles_.template increment<dimension>(this->shape()[dimension]);
    00767     }
    00768
    00769     void moveRelative(typename value_type::shape_type const & coordOffset)
    00770     {
    00771         base_type::moveRelative(coordOffset);
    00772         this->handles_.template increment<dimension>(coordOffset[dimension]);
    00773     }
    00774 };
    00775
    00776
    00777
    00778 template <unsigned int N, class HANDLES>
    00779 class CoupledScanOrderIterator<N, HANDLES, 0>
    00780 {
    00781     static const int dimension = 0;
    00782
    00783   public:
    00784
    00785     typedef CoupledScanOrderIterator<N, HANDLES, 0>  self_type;
    00786     typedef HANDLES                                  value_type;
    00787     typedef MultiArrayIndex                          difference_type;
    00788     typedef value_type &                             reference;
    00789     typedef value_type const &                       const_reference;
    00790     typedef value_type *                             pointer;
    00791     typedef typename MultiArrayShape<1>::type        shape_type;
    00792     typedef CoupledScanOrderIterator                 iterator;
    00793     typedef std::random_access_iterator_tag          iterator_category;
    00794
    00795     CoupledScanOrderIterator(value_type const & handles = value_type())
    00796     : handles_(handles)
    00797     {}
    00798
    00799     CoupledScanOrderIterator & operator++()
    00800     {
    00801         handles_.template increment<dimension>();
    00802         handles_.incrementIndex();
    00803         return *this;
    00804     }
    00805
    00806     CoupledScanOrderIterator operator++(int)
    00807     {
    00808         CoupledScanOrderIterator res(*this);
    00809         ++*this;
    00810         return res;
    00811     }
    00812
    00813     CoupledScanOrderIterator & operator+=(MultiArrayIndex i)
    00814     {
    00815         shape_type coordOffset;
    00816         detail::ScanOrderToCoordinate<N>::exec(i, shape(), coordOffset);
    00817         moveRelative(coordOffset);
    00818         handles_.scanOrderIndex_ += i;
    00819         return *this;
    00820     }
    00821
    00822     CoupledScanOrderIterator & operator+=(const shape_type &coordOffset)
    00823     {
    00824         moveRelative(coordOffset);
    00825         handles_.scanOrderIndex_ += detail::CoordinateToScanOrder<N>::exec(shape(), coordOffset);
    00826         return *this;
    00827     }
    00828
    00829     CoupledScanOrderIterator & operator-=(const shape_type &coordOffset)
    00830     {
    00831         return operator+=(-coordOffset);
    00832     }
    00833
    00834     CoupledScanOrderIterator & operator--()
    00835     {
    00836         handles_.template decrement<dimension>();
    00837         handles_.decrementIndex();
    00838         return *this;
    00839     }
    00840
    00841     CoupledScanOrderIterator operator--(int)
    00842     {
    00843         CoupledScanOrderIterator res(*this);
    00844         --this;
    00845         return res;
    00846     }
    00847
    00848     CoupledScanOrderIterator & operator-=(MultiArrayIndex i)
    00849     {
    00850         return operator+=(-i);
    00851     }
    00852
    00853     value_type operator[](MultiArrayIndex i) const
    00854     {
    00855         return *(CoupledScanOrderIterator(*this) += i);
    00856     }
    00857
    00858     CoupledScanOrderIterator
    00859     operator+(MultiArrayIndex d) const
    00860     {
    00861         return CoupledScanOrderIterator(*this) += d;
    00862     }
    00863
    00864     CoupledScanOrderIterator
    00865     operator-(MultiArrayIndex d) const
    00866     {
    00867         return CoupledScanOrderIterator(*this) -= d;
    00868     }
    00869
    00870     CoupledScanOrderIterator operator+(const shape_type &coordOffset) const
    00871     {
    00872         return CoupledScanOrderIterator(*this) += coordOffset;
    00873     }
    00874
    00875     CoupledScanOrderIterator operator-(const shape_type &coordOffset) const
    00876     {
    00877         return CoupledScanOrderIterator(*this) -= coordOffset;
    00878     }
    00879
    00880     MultiArrayIndex
    00881     operator-(CoupledScanOrderIterator const & r) const
    00882     {
    00883         return scanOrderIndex() - r.scanOrderIndex();
    00884     }
    00885
    00886     bool
    00887     operator==(CoupledScanOrderIterator const & r)
    00888     {
    00889         return scanOrderIndex() == r.scanOrderIndex();
    00890     }
    00891
    00892     bool
    00893     operator!=(CoupledScanOrderIterator const & r) const
    00894     {
    00895         return scanOrderIndex() != r.scanOrderIndex();
    00896     }
    00897
    00898     bool
    00899     operator<(CoupledScanOrderIterator const & r) const
    00900     {
    00901         return scanOrderIndex() < r.scanOrderIndex();
    00902     }
    00903
    00904     bool
    00905     operator<=(CoupledScanOrderIterator const & r) const
    00906     {
    00907         return scanOrderIndex() <= r.scanOrderIndex();
    00908     }
    00909
    00910     bool
    00911     operator>(CoupledScanOrderIterator const & r) const
    00912     {
    00913         return scanOrderIndex() > r.scanOrderIndex();
    00914     }
    00915
    00916     bool
    00917     operator>=(CoupledScanOrderIterator const & r) const
    00918     {
    00919         return scanOrderIndex() >= r.scanOrderIndex();
    00920     }
    00921
    00922     MultiArrayIndex scanOrderIndex() const
    00923     {
    00924         return handles_.scanOrderIndex();
    00925     }
    00926
    00927     typename value_type::shape_type const & point() const
    00928     {
    00929         return handles_.point();
    00930     }
    00931
    00932     typename value_type::shape_type const & shape() const
    00933     {
    00934         return handles_.shape();
    00935     }
    00936
    00937     reference operator*()
    00938     {
    00939         return handles_;
    00940     }
    00941
    00942     const_reference operator*() const
    00943     {
    00944         return handles_;
    00945     }
    00946
    00947     void restrictToSubarray(shape_type const & start, shape_type const & end) const
    00948     {
    00949         operator+=(-point());
    00950         handles_.restricToSubarray(start, end);
    00951     }
    00952
    00953     CoupledScanOrderIterator getEndIterator() const
    00954     {
    00955         return operator+(prod(shape()));
    00956     }
    00957
    00958     bool atBorder() const
    00959     {
    00960         return (handles_.neighborhoodType() != 0);
    00961     }
    00962
    00963     unsigned int neighborhoodType() const
    00964     {
    00965         return handles_.neighborhoodType();
    00966     }
    00967
    00968     template<unsigned int TARGET_INDEX>
    00969     typename CoupledHandleCast<TARGET_INDEX, value_type>::type::reference
    00970     get()
    00971     {
    00972         return vigra::get<TARGET_INDEX>(handles_);
    00973     }
    00974
    00975     template<unsigned int TARGET_INDEX>
    00976     typename CoupledHandleCast<TARGET_INDEX, value_type>::type::const_reference
    00977     get() const
    00978     {
    00979         return vigra::get<TARGET_INDEX>(handles_);
    00980     }
    00981
    00982   protected:
    00983     void reset()
    00984     {
    00985         handles_.template decrement<dimension>(shape()[dimension]);
    00986     }
    00987
    00988     void inverseReset()
    00989     {
    00990         handles_.template increment<dimension>(shape()[dimension]);
    00991     }
    00992
    00993     void moveRelative(typename value_type::shape_type const & coordOffset)
    00994     {
    00995         handles_.template increment<dimension>(coordOffset[dimension]);
    00996     }
    00997
    00998     value_type handles_;
    00999 };
    01000
    01001
    01002 template <unsigned int N, class List>
    01003 struct ComposeCoupledHandle;
    01004
    01005 template <unsigned int N, class T, class TAIL>
    01006 struct ComposeCoupledHandle<N, TypeList<T, TAIL> >
    01007 {
    01008     typedef typename ComposeCoupledHandle<N, TAIL>::type  BaseType;
    01009     typedef typename MultiArrayShape<N>::type             shape_type;
    01010     typedef CoupledHandle<T, BaseType>                    type;
    01011
    01012     template <class S>
    01013     type exec(MultiArrayView<N, T, S> const & m,
    01014               shape_type const & start, shape_type const & end,
    01015               BaseType const & base)
    01016     {
    01017         return type(m.subarray(start, end).data(), m.stride(), base);
    01018     }
    01019
    01020     template <class S>
    01021     type exec(MultiArrayView<N, T, S> const & m, BaseType const & base)
    01022     {
    01023         return type(m.data(), m.stride(), base);
    01024     }
    01025 };
    01026
    01027 template <unsigned int N>
    01028 struct ComposeCoupledHandle<N, void>
    01029 {
    01030     typedef typename MultiArrayShape<N>::type  shape_type;
    01031     typedef CoupledHandle<shape_type, void>    type;
    01032
    01033     type exec(shape_type const & shape)
    01034     {
    01035         return type(shape);
    01036     }
    01037
    01038     type exec(shape_type const & start, shape_type const & end)
    01039     {
    01040         return type(end-start);
    01041     }
    01042 };
    01043
    01044 template <unsigned int N, class T1=void, class T2=void, class T3=void, class T4=void, class T5=void>
    01045 struct CoupledHandleType
    01046 {
    01047     // reverse the order to get the desired index order
    01048     typedef typename MakeTypeList<T5, T4, T3, T2, T1>::type TypeList;
    01049     typedef typename ComposeCoupledHandle<N, TypeList>::type type;
    01050 };
    01051
    01052 template <unsigned int N, class T1, class T2, class T3, class T4, class T5>
    01053 struct CoupledHandleType<N, Multiband<T1>, T2, T3, T4, T5>
    01054 {
    01055     // reverse the order to get the desired index order
    01056     typedef typename MakeTypeList<T5, T4, T3, T2, Multiband<T1> >::type TypeList;
    01057     typedef typename ComposeCoupledHandle<N-1, TypeList>::type type;
    01058 };
    01059
    01060 /** 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.
    01061  */
    01062 template <unsigned int N, class T1=void, class T2=void, class T3=void, class T4=void, class T5=void>
    01063 struct CoupledIteratorType
    01064 {
    01065     /** Type of the CoupledHandle.*/
    01066     typedef typename CoupledHandleType<N, T1, T2, T3, T4, T5>::type HandleType;
    01067
    01068     /** Type of the CoupledScanOrderIterator.*/
    01069     typedef CoupledScanOrderIterator<HandleType::dimensions, HandleType> type;
    01070 };
    01071
    01072 /** Returns a CoupledScanOrderIterator from shape to iterate over coordinates.
    01073  */
    01074 template <int N>
    01075 typename CoupledIteratorType<N>::type
    01076 createCoupledIterator(TinyVector<MultiArrayIndex, N> const & shape)
    01077 {
    01078     typedef typename CoupledHandleType<N>::type   P0;
    01079     typedef CoupledScanOrderIterator<N, P0> IteratorType;
    01080
    01081     return IteratorType(P0(shape));
    01082 }
    01083
    01084 /** Returns a CoupledScanOrderIterator to simultaneously iterate over image m1 and its coordinates.
    01085  */
    01086 template <unsigned int N1, class T1, class S1>
    01087 typename CoupledIteratorType<N1, T1>::type
    01088 createCoupledIterator(MultiArrayView<N1, T1, S1> const & m1)
    01089 {
    01090     typedef typename CoupledHandleType<N1, T1>::type             P1;
    01091     typedef typename P1::base_type                               P0;
    01092     typedef CoupledScanOrderIterator<P1::dimensions, P1>         IteratorType;
    01093
    01094     return IteratorType(P1(m1,
    01095                         P0(m1.shape())));
    01096 }
    01097
    01098 /** Returns a CoupledScanOrderIterator to simultaneously iterate over images m1, m2 and their coordinates.
    01099  */
    01100 template <unsigned int N1, class T1, class S1,
    01101           unsigned int N2, class T2, class S2>
    01102 typename CoupledIteratorType<N1, T1, T2>::type
    01103 createCoupledIterator(MultiArrayView<N1, T1, S1> const & m1,
    01104                       MultiArrayView<N2, T2, S2> const & m2)
    01105 {
    01106     typedef typename CoupledHandleType<N1, T1, T2>::type         P2;
    01107     typedef typename P2::base_type                               P1;
    01108     typedef typename P1::base_type                               P0;
    01109     typedef CoupledScanOrderIterator<P2::dimensions, P2> IteratorType;
    01110
    01111     return IteratorType(P2(m2,
    01112                         P1(m1,
    01113                         P0(m1.shape()))));
    01114 }
    01115
    01116 /** Returns a CoupledScanOrderIterator to simultaneously iterate over images m1, m2, m3 and their coordinates.
    01117  */
    01118 template <unsigned int N1, class T1, class S1,
    01119           unsigned int N2, class T2, class S2,
    01120           unsigned int N3, class T3, class S3>
    01121 typename CoupledIteratorType<N1, T1, T2, T3>::type
    01122 createCoupledIterator(MultiArrayView<N1, T1, S1> const & m1,
    01123                       MultiArrayView<N2, T2, S2> const & m2,
    01124                       MultiArrayView<N3, T3, S3> const & m3)
    01125 {
    01126     typedef typename CoupledHandleType<N1, T1, T2, T3>::type     P3;
    01127     typedef typename P3::base_type                               P2;
    01128     typedef typename P2::base_type                               P1;
    01129     typedef typename P1::base_type                               P0;
    01130     typedef CoupledScanOrderIterator<P3::dimensions, P3> IteratorType;
    01131
    01132     return IteratorType(P3(m3,
    01133                         P2(m2,
    01134                         P1(m1,
    01135                         P0(m1.shape())))));
    01136 }
    01137
    01138 /** Returns a CoupledScanOrderIterator to simultaneously iterate over images m1, m2, m3, m4 and their coordinates.
    01139  */
    01140 template <unsigned int N1, class T1, class S1,
    01141           unsigned int N2, class T2, class S2,
    01142           unsigned int N3, class T3, class S3,
    01143           unsigned int N4, class T4, class S4>
    01144 typename CoupledIteratorType<N1, T1, T2, T3, T4>::type
    01145 createCoupledIterator(MultiArrayView<N1, T1, S1> const & m1,
    01146                       MultiArrayView<N2, T2, S2> const & m2,
    01147                       MultiArrayView<N3, T3, S3> const & m3,
    01148                       MultiArrayView<N4, T4, S4> const & m4)
    01149 {
    01150     typedef typename CoupledHandleType<N1, T1, T2, T3, T4>::type P4;
    01151     typedef typename P4::base_type                               P3;
    01152     typedef typename P3::base_type                               P2;
    01153     typedef typename P2::base_type                               P1;
    01154     typedef typename P1::base_type                               P0;
    01155     typedef CoupledScanOrderIterator<P4::dimensions, P4> IteratorType;
    01156
    01157     return IteratorType(P4(m4,
    01158                         P3(m3,
    01159                         P2(m2,
    01160                         P1(m1,
    01161                         P0(m1.shape()))))));
    01162 }
    01163
    01164 /** Returns a CoupledScanOrderIterator to simultaneously iterate over images m1, m2, m3, m4, m5 and their coordinates.
    01165  */
    01166 template <unsigned int N1, class T1, class S1,
    01167           unsigned int N2, class T2, class S2,
    01168           unsigned int N3, class T3, class S3,
    01169           unsigned int N4, class T4, class S4,
    01170           unsigned int N5, class T5, class S5>
    01171 typename CoupledIteratorType<N1, T1, T2, T3, T4, T5>::type
    01172 createCoupledIterator(MultiArrayView<N1, T1, S1> const & m1,
    01173                       MultiArrayView<N2, T2, S2> const & m2,
    01174                       MultiArrayView<N3, T3, S3> const & m3,
    01175                       MultiArrayView<N4, T4, S4> const & m4,
    01176                       MultiArrayView<N5, T5, S5> const & m5)
    01177 {
    01178     typedef typename CoupledHandleType<N1, T1, T2, T3, T4, T5>::type P5;
    01179     typedef typename P5::base_type                                   P4;
    01180     typedef typename P4::base_type                                   P3;
    01181     typedef typename P3::base_type                                   P2;
    01182     typedef typename P2::base_type                                   P1;
    01183     typedef typename P1::base_type                                   P0;
    01184     typedef CoupledScanOrderIterator<P1::dimensions, P5> IteratorType;
    01185
    01186     return IteratorType(P5(m5,
    01187                         P4(m4,
    01188                         P3(m3,
    01189                         P2(m2,
    01190                         P1(m1,
    01191                         P0(m1.shape())))))));
    01192 }
    01193
    01194 //@}
    01195
    01196 } // namespace vigra
    01197
    01198 #endif /* MULTI_ITERATOR_COUPLED_HXX_ */

© 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.9.0 (Tue Nov 6 2012)