[ 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.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) |
html generated using doxygen and Python
|