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

details vigra/navigator.hxx VIGRA

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.3, Aug 18 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.3 (18 Aug 2005)