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