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

| vigra/navigator.hxx |
--- | --- | ---

    00001 /************************************************************************/
    00002 /*                                                                      */
    00003 /*                Copyright 2004 by Ullrich Koethe                      */
    00004 /*       Cognitive Systems Group, University of Hamburg, Germany        */
    00005 /*                                                                      */
    00006 /*    This file is part of the VIGRA computer vision library.           */
    00007 /*    ( Version 1.3.2, Jan 27 2005 )                                    */
    00008 /*    You may use, modify, and distribute this software according       */
    00009 /*    to the terms stated in the LICENSE file included in               */
    00010 /*    the VIGRA distribution.                                           */
    00011 /*                                                                      */
    00012 /*    The VIGRA Website is                                              */
    00013 /*        http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/      */
    00014 /*    Please direct questions, bug reports, and contributions to        */
    00015 /*        koethe@informatik.uni-hamburg.de                              */
    00016 /*                                                                      */
    00017 /*  THIS SOFTWARE IS PROVIDED AS IS AND WITHOUT ANY EXPRESS OR          */
    00018 /*  IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED      */
    00019 /*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
    00020 /*                                                                      */
    00021 /************************************************************************/
    00022
    00023 #ifndef VIGRA_NAVIGATOR_HXX
    00024 #define VIGRA_NAVIGATOR_HXX
    00025
    00026 namespace vigra {
    00027
    00028 /********************************************************/
    00029 /*                                                      */
    00030 /*                MultiArrayNavigator                   */
    00031 /*                                                      */
    00032 /********************************************************/
    00033
    00034 /** \brief A navigator that provides acces to the 1D subranges of an
    00035     n-dimensional range given by a \ref vigra::MultiIterator and an nD shape.
    00036
    00037     Normally, the innermost loop of an iteration extends over the innermost
    00038     dimension of a given array. Sometimes, however, it is necessary to have
    00039     some other dimension in the inner loop. For example, instead of iterating over
    00040     the rows, the inner loop should extend over the columns. The class MultiArrayNavigator
    00041     encapsulates the necessary functionality. Given an arbitrary dimensional
    00042     array (represented by a vigra::MultiIterator/shape pair), and the desired
    00043     inner loop dimension <TT>d</TT>, it moves the encapsulated iterator to all possible
    00044     starting points of 1D subsets along the given dimension (e.g. all columns). By calling
    00045     <TT>begin()</TT> and <TT>end()</TT>, one can then obtain an STL-compatible 1-dimensional
    00046     iterator for the current subset.
    00047
    00048     The template parameters specify the embedded iterator type and its dimension.
    00049
    00050     <b>Usage:</b>
    00051
    00052     <b>\#include</b> "<a href="navigator_8hxx-source.html">vigra/navigator.hxx</a>"
    00053
    00054     Namespace: vigra
    00055
    00056     \code
    00057     typedef vigra::MultiArray<3, int>  Array;
    00058
    00059     Array a(Array::size_type(X, Y, Z));
    00060
    00061     typedef vigra::MultiArrayNavigator<Array::traverser, 3> Navigator;
    00062
    00063     for(int d=0; d<3; ++d)
    00064     {
    00065         // create Navigator for dimension d
    00066         Navigator nav(a.traverser_begin(), a.shape(), d);
    00067
    00068         // outer loop: move navigator to all starting points
    00069         // of 1D subsets that run parallel to coordinate axis d
    00070         for(; nav.hasMore(); ++nav)
    00071         {
    00072             // inner loop: linear iteration over current subset
    00073             //             d == {0, 1, 2}: interate along {x, y, z}-axis respectively
    00074              Navigator::iterator i = nav.begin(), end = nav.end();
    00075             for(; i != end; ++i)
    00076                 // do something
    00077         }
    00078     }
    00079     \endcode
    00080 */
    00081 template <class MULTI_ITERATOR, unsigned int N>
    00082 class MultiArrayNavigator
    00083 #ifndef DOXYGEN  // doxygen doesn't understand this inheritance
    00084 : public MultiArrayNavigator<MULTI_ITERATOR, N-1>
    00085 #endif
    00086 {
    00087     typedef MultiArrayNavigator<MULTI_ITERATOR, N-1> base_type;
    00088
    00089   public:
    00090     enum { level = N-1 };
    00091
    00092         /** The required shape type for the given iterator type.
    00093          */
    00094     typedef typename MULTI_ITERATOR::multi_difference_type shape_type;
    00095
    00096         /** The iterator type for the inner loop (result of begin() and end()).
    00097          */
    00098     typedef typename MULTI_ITERATOR::iterator iterator;
    00099
    00100         /** Construct navigator for multi-dimensional iterator <TT>i</TT>, array shape <TT>shape</TT>
    00101             and inner loop dimension <TT>inner_dimension</TT>.
    00102          */
    00103     MultiArrayNavigator(MULTI_ITERATOR const & i, shape_type const & shape, unsigned int inner_dimension)
    00104     : base_type(i, shape, inner_dimension),
    00105       i_(i),
    00106       end_(i)
    00107     {
    00108         if(inner_dimension != level)
    00109             end_.template dim<level>() += shape[level];
    00110     }
    00111
    00112         /** Advance to next starting location.
    00113          */
    00114     void operator++()
    00115     {
    00116         base_type::operator++();
    00117         if(base_type::atEnd() && i_ < end_) // this tests implicitly inner_dimension_ != level
    00118         {
    00119             ++i_.template dim<level>();
    00120             if(i_ < end_)
    00121                 base_type::reset(i_);
    00122         }
    00123     }
    00124
    00125         /** Advance to next starting location.
    00126          */
    00127     void operator++(int)
    00128     {
    00129         ++*this;
    00130     }
    00131
    00132         /** true if there are more elements.
    00133          */
    00134     bool hasMore() const
    00135     {
    00136         return this->inner_dimension_ == level ?
    00137                     base_type::hasMore() :
    00138                     i_ < end_;
    00139     }
    00140
    00141         /** true if iterator is exhausted.
    00142          */
    00143     bool atEnd() const
    00144     {
    00145         return this->inner_dimension_ == level ?
    00146                     base_type::atEnd() :
    00147                 !( i_ < end_);
    00148     }
    00149
    00150   protected:
    00151     void reset(MULTI_ITERATOR const & i)
    00152     {
    00153         end_ = i_ = i;
    00154         if(this->inner_dimension_ != level)
    00155             end_.template dim<level>() += this->shape_[level];
    00156         base_type::reset(i);
    00157     }
    00158
    00159     MULTI_ITERATOR i_, end_;
    00160 };
    00161
    00162 template <class MULTI_ITERATOR>
    00163 class MultiArrayNavigator<MULTI_ITERATOR, 1>
    00164 {
    00165   public:
    00166     enum { level = 0 };
    00167     typedef typename MULTI_ITERATOR::multi_difference_type shape_type;
    00168     typedef typename MULTI_ITERATOR::iterator iterator;
    00169
    00170     MultiArrayNavigator(MULTI_ITERATOR const & i, shape_type const & shape, unsigned int inner_dimension)
    00171     : shape_(shape),
    00172       inner_dimension_(inner_dimension),
    00173       i_(i),
    00174       end_(i)
    00175     {
    00176         if(inner_dimension != level)
    00177             end_.template dim<level>() += shape[level];
    00178     }
    00179
    00180     void operator++()
    00181     {
    00182         ++i_.template dim<level>();
    00183     }
    00184
    00185     void operator++(int)
    00186     {
    00187         ++*this;
    00188     }
    00189
    00190     iterator begin() const
    00191     {
    00192         return i_.iteratorForDimension(inner_dimension_);
    00193     }
    00194
    00195     iterator end() const
    00196     {
    00197         return begin() + shape_[inner_dimension_];
    00198     }
    00199
    00200     bool hasMore() const
    00201     {
    00202         return i_ < end_;
    00203     }
    00204
    00205     bool atEnd() const
    00206     {
    00207       return !( i_ < end_);
    00208     }
    00209
    00210   protected:
    00211     void reset(MULTI_ITERATOR const & i)
    00212     {
    00213         end_ = i_ = i;
    00214         if(inner_dimension_ != level)
    00215             end_.template dim<level>() += shape_[level];
    00216     }
    00217
    00218     shape_type shape_;
    00219     unsigned int inner_dimension_;
    00220     MULTI_ITERATOR i_, end_;
    00221 };
    00222
    00223 } // namespace vigra
    00224
    00225 #endif /* VIGRA_NAVIGATOR_HXX */

© Ullrich Köthe (koethe@informatik.uni-hamburg.de) Cognitive Systems Group, University of Hamburg, Germany | html generated using doxygen and Python VIGRA 1.3.2 (27 Jan 2005)