[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | 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.6.0, Aug 13 2008 )                                    */
    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 /*        ullrich.koethe@iwr.uni-heidelberg.de    or                    */
    00012 /*        vigra@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 (ullrich.koethe@iwr.uni-heidelberg.de) Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany | html generated using doxygen and Python VIGRA 1.6.0 (13 Aug 2008)