[ 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.4.0, Dec 21 2005 )                                    */
00008 /*    The VIGRA Website is                                              */
00009 /*        http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/      */
00010 /*    Please direct questions, bug reports, and contributions to        */
00011 /*        koethe@informatik.uni-hamburg.de          or                  */
00012 /*        vigra@kogs1.informatik.uni-hamburg.de                         */
00013 /*                                                                      */
00014 /*    Permission is hereby granted, free of charge, to any person       */
00015 /*    obtaining a copy of this software and associated documentation    */
00016 /*    files (the "Software"), to deal in the Software without           */
00017 /*    restriction, including without limitation the rights to use,      */
00018 /*    copy, modify, merge, publish, distribute, sublicense, and/or      */
00019 /*    sell copies of the Software, and to permit persons to whom the    */
00020 /*    Software is furnished to do so, subject to the following          */
00021 /*    conditions:                                                       */
00022 /*                                                                      */
00023 /*    The above copyright notice and this permission notice shall be    */
00024 /*    included in all copies or substantial portions of the             */
00025 /*    Software.                                                         */
00026 /*                                                                      */
00027 /*    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND    */
00028 /*    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES   */
00029 /*    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND          */
00030 /*    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT       */
00031 /*    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,      */
00032 /*    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING      */
00033 /*    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR     */
00034 /*    OTHER DEALINGS IN THE SOFTWARE.                                   */                
00035 /*                                                                      */
00036 /************************************************************************/
00037 
00038 #ifndef VIGRA_NAVIGATOR_HXX
00039 #define VIGRA_NAVIGATOR_HXX
00040 
00041 namespace vigra {
00042 
00043 /********************************************************/
00044 /*                                                      */
00045 /*                MultiArrayNavigator                   */
00046 /*                                                      */
00047 /********************************************************/
00048 
00049 /** \brief A navigator that provides acces to the 1D subranges of an
00050     n-dimensional range given by a \ref vigra::MultiIterator and an nD shape.
00051 
00052     Normally, the innermost loop of an iteration extends over the innermost
00053     dimension of a given array. Sometimes, however, it is necessary to have
00054     some other dimension in the inner loop. For example, instead of iterating over
00055     the rows, the inner loop should extend over the columns. The class MultiArrayNavigator
00056     encapsulates the necessary functionality. Given an arbitrary dimensional
00057     array (represented by a vigra::MultiIterator/shape pair), and the desired
00058     inner loop dimension <TT>d</TT>, it moves the encapsulated iterator to all possible
00059     starting points of 1D subsets along the given dimension (e.g. all columns). By calling
00060     <TT>begin()</TT> and <TT>end()</TT>, one can then obtain an STL-compatible 1-dimensional
00061     iterator for the current subset.
00062 
00063     The template parameters specify the embedded iterator type and its dimension.
00064 
00065     <b>Usage:</b>
00066 
00067     <b>\#include</b> "<a href="navigator_8hxx-source.html">vigra/navigator.hxx</a>"
00068 
00069     Namespace: vigra
00070 
00071     \code
00072     typedef vigra::MultiArray<3, int>  Array;
00073 
00074     Array a(Array::size_type(X, Y, Z));
00075 
00076     typedef vigra::MultiArrayNavigator<Array::traverser, 3> Navigator;
00077 
00078     for(int d=0; d<3; ++d)
00079     {
00080         // create Navigator for dimension d
00081         Navigator nav(a.traverser_begin(), a.shape(), d);
00082 
00083         // outer loop: move navigator to all starting points
00084         // of 1D subsets that run parallel to coordinate axis d
00085         for(; nav.hasMore(); ++nav)
00086         {
00087             // inner loop: linear iteration over current subset
00088             //             d == {0, 1, 2}: interate along {x, y, z}-axis respectively
00089              Navigator::iterator i = nav.begin(), end = nav.end();
00090             for(; i != end; ++i)
00091                 // do something
00092         }
00093     }
00094     \endcode
00095 */
00096 template <class MULTI_ITERATOR, unsigned int N>
00097 class MultiArrayNavigator
00098 #ifndef DOXYGEN  // doxygen doesn't understand this inheritance
00099 : public MultiArrayNavigator<MULTI_ITERATOR, N-1>
00100 #endif
00101 {
00102     typedef MultiArrayNavigator<MULTI_ITERATOR, N-1> base_type;
00103 
00104   public:
00105     enum { level = N-1 };
00106 
00107         /** The required shape type for the given iterator type.
00108          */
00109     typedef typename MULTI_ITERATOR::multi_difference_type shape_type;
00110 
00111         /** The iterator type for the inner loop (result of begin() and end()).
00112          */
00113     typedef typename MULTI_ITERATOR::iterator iterator;
00114 
00115         /** Construct navigator for multi-dimensional iterator <TT>i</TT>, array shape <TT>shape</TT>
00116             and inner loop dimension <TT>inner_dimension</TT>.
00117          */
00118     MultiArrayNavigator(MULTI_ITERATOR const & i, shape_type const & shape, unsigned int inner_dimension)
00119     : base_type(i, shape, inner_dimension),
00120       i_(i),
00121       end_(i)
00122     {
00123         if(inner_dimension != level)
00124             end_.template dim<level>() += shape[level];
00125     }
00126 
00127         /** Advance to next starting location.
00128          */
00129     void operator++()
00130     {
00131         base_type::operator++();
00132         if(base_type::atEnd() && i_ < end_) // this tests implicitly inner_dimension_ != level
00133         {
00134             ++i_.template dim<level>();
00135             if(i_ < end_)
00136                 base_type::reset(i_);
00137         }
00138     }
00139 
00140         /** Advance to next starting location.
00141          */
00142     void operator++(int)
00143     {
00144         ++*this;
00145     }
00146 
00147         /** true if there are more elements.
00148          */
00149     bool hasMore() const
00150     {
00151         return this->inner_dimension_ == level ?
00152                     base_type::hasMore() :
00153                     i_ < end_;
00154     }
00155 
00156         /** true if iterator is exhausted.
00157          */
00158     bool atEnd() const
00159     {
00160         return this->inner_dimension_ == level ?
00161                     base_type::atEnd() :
00162                 !( i_ < end_);
00163     }
00164 
00165   protected:
00166     void reset(MULTI_ITERATOR const & i)
00167     {
00168         end_ = i_ = i;
00169         if(this->inner_dimension_ != level)
00170             end_.template dim<level>() += this->shape_[level];
00171         base_type::reset(i);
00172     }
00173 
00174     MULTI_ITERATOR i_, end_;
00175 };
00176 
00177 template <class MULTI_ITERATOR>
00178 class MultiArrayNavigator<MULTI_ITERATOR, 1>
00179 {
00180   public:
00181     enum { level = 0 };
00182     typedef typename MULTI_ITERATOR::multi_difference_type shape_type;
00183     typedef typename MULTI_ITERATOR::iterator iterator;
00184 
00185     MultiArrayNavigator(MULTI_ITERATOR const & i, shape_type const & shape, unsigned int inner_dimension)
00186     : shape_(shape),
00187       inner_dimension_(inner_dimension),
00188       i_(i),
00189       end_(i)
00190     {
00191         if(inner_dimension != level)
00192             end_.template dim<level>() += shape[level];
00193     }
00194 
00195     void operator++()
00196     {
00197         ++i_.template dim<level>();
00198     }
00199 
00200     void operator++(int)
00201     {
00202         ++*this;
00203     }
00204 
00205     iterator begin() const
00206     {
00207         return i_.iteratorForDimension(inner_dimension_);
00208     }
00209 
00210     iterator end() const
00211     {
00212         return begin() + shape_[inner_dimension_];
00213     }
00214 
00215     bool hasMore() const
00216     {
00217         return i_ < end_;
00218     }
00219 
00220     bool atEnd() const
00221     {
00222       return !( i_ < end_);
00223     }
00224 
00225   protected:
00226     void reset(MULTI_ITERATOR const & i)
00227     {
00228         end_ = i_ = i;
00229         if(inner_dimension_ != level)
00230             end_.template dim<level>() += shape_[level];
00231     }
00232 
00233     shape_type shape_;
00234     unsigned int inner_dimension_;
00235     MULTI_ITERATOR i_, end_;
00236 };
00237 
00238 } // namespace vigra
00239 
00240 #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.4.0 (21 Dec 2005)