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

navigator.hxx VIGRA

1 /************************************************************************/
2 /* */
3 /* Copyright 2004 by Ullrich Koethe */
4 /* */
5 /* This file is part of the VIGRA computer vision library. */
6 /* The VIGRA Website is */
7 /* http://hci.iwr.uni-heidelberg.de/vigra/ */
8 /* Please direct questions, bug reports, and contributions to */
9 /* ullrich.koethe@iwr.uni-heidelberg.de or */
10 /* vigra@informatik.uni-hamburg.de */
11 /* */
12 /* Permission is hereby granted, free of charge, to any person */
13 /* obtaining a copy of this software and associated documentation */
14 /* files (the "Software"), to deal in the Software without */
15 /* restriction, including without limitation the rights to use, */
16 /* copy, modify, merge, publish, distribute, sublicense, and/or */
17 /* sell copies of the Software, and to permit persons to whom the */
18 /* Software is furnished to do so, subject to the following */
19 /* conditions: */
20 /* */
21 /* The above copyright notice and this permission notice shall be */
22 /* included in all copies or substantial portions of the */
23 /* Software. */
24 /* */
25 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
26 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
27 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
28 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
29 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
30 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
31 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
32 /* OTHER DEALINGS IN THE SOFTWARE. */
33 /* */
34 /************************************************************************/
35 
36 #ifndef VIGRA_NAVIGATOR_HXX
37 #define VIGRA_NAVIGATOR_HXX
38 
39 #include "multi_shape.hxx"
40 
41 namespace vigra {
42 
43 /********************************************************/
44 /* */
45 /* MultiArrayNavigator */
46 /* */
47 /********************************************************/
48 
49 /** \brief A navigator that provides access to the 1D subranges of an
50  n-dimensional range given by a \ref vigra::MultiIterator and an nD shape.
51 
52  Normally, the innermost loop of an iteration extends over the innermost
53  dimension of a given array. Sometimes, however, it is necessary to have
54  some other dimension in the inner loop. For example, instead of iterating over
55  the rows, the inner loop should extend over the columns. The class MultiArrayNavigator
56  encapsulates the necessary functionality. Given an arbitrary dimensional
57  array (represented by a vigra::MultiIterator/shape pair), and the desired
58  inner loop dimension <TT>d</TT>, it moves the encapsulated iterator to all possible
59  starting points of 1D subsets along the given dimension (e.g. all columns). By calling
60  <TT>begin()</TT> and <TT>end()</TT>, one can then obtain an STL-compatible 1-dimensional
61  iterator for the current subset.
62 
63  The template parameters specify the embedded iterator type and its dimension.
64 
65  <b>Usage:</b>
66 
67  <b>\#include</b> <vigra/navigator.hxx>
68 
69  Namespace: vigra
70 
71  \code
72  typedef vigra::MultiArray<3, int> Array;
73 
74  Array a(Array::size_type(X, Y, Z));
75 
76  typedef vigra::MultiArrayNavigator<Array::traverser, 3> Navigator;
77 
78  for(int d=0; d<3; ++d)
79  {
80  // create Navigator for dimension d
81  Navigator nav(a.traverser_begin(), a.shape(), d);
82 
83  // outer loop: move navigator to all starting points
84  // of 1D subsets that run parallel to coordinate axis d
85  for(; nav.hasMore(); ++nav)
86  {
87  // inner loop: linear iteration over current subset
88  // d == {0, 1, 2}: iterate along {x, y, z}-axis respectively
89  Navigator::iterator i = nav.begin(), end = nav.end();
90  for(; i != end; ++i)
91  // do something
92  }
93  }
94  \endcode
95 */
96 template <class MULTI_ITERATOR, unsigned int N>
98 #ifndef DOXYGEN // doxygen doesn't understand this inheritance
99 : public MultiArrayNavigator<MULTI_ITERATOR, N-1>
100 #endif
101 {
102  typedef MultiArrayNavigator<MULTI_ITERATOR, N-1> base_type;
103 
104  public:
105  enum { level = N-1 };
106 
107  /** The required shape type for the given iterator type.
108  */
109  typedef typename MULTI_ITERATOR::multi_difference_type shape_type;
110 
111  /** The iterator type for the inner loop (result of begin() and end()).
112  */
113  typedef typename MULTI_ITERATOR::iterator iterator;
114 
115  /** Construct navigator for multi-dimensional iterator <TT>i</TT>, array shape <TT>shape</TT>
116  and inner loop dimension <TT>inner_dimension</TT>.
117  */
118  MultiArrayNavigator(MULTI_ITERATOR const & i, shape_type const & shape, unsigned int inner_dimension)
119  : base_type(i, shape, inner_dimension)
120  {}
121 
122  MultiArrayNavigator(MULTI_ITERATOR const & i, shape_type const & start, shape_type const & stop,
123  unsigned int inner_dimension)
124  : base_type(i, start, stop, inner_dimension)
125  {}
126 
127  /** Advance to next starting location.
128  */
129  void operator++()
130  {
132  if(this->point_[level-1] == this->stop_[level-1])
133  {
134  base_type::reset();
135  ++this->point_[level];
136  ++this->i_.template dim<level>();
137  }
138  }
139 
140  /** Advance to next starting location.
141  */
142  void operator++(int)
143  {
144  ++*this;
145  }
146 
147  /** true if there are more elements.
148  */
149  bool hasMore() const
150  {
151  return this->point_[level] < this->stop_[level];
152  }
153 
154  /** true if iterator is exhausted.
155  */
156  bool atEnd() const
157  {
158  return this->point_[level] >= this->stop_[level];
159  }
160 
161  protected:
162  void reset()
163  {
164  this->point_[level] = this->start_[level];
165  this->i_.template dim<level>() -= (this->stop_[level] - this->start_[level]);
166  }
167 };
168 
169 template <class MULTI_ITERATOR>
170 class MultiArrayNavigator<MULTI_ITERATOR, 1>
171 {
172  public:
173  enum { level = 0 };
174  typedef typename MULTI_ITERATOR::multi_difference_type shape_type;
175  typedef typename MULTI_ITERATOR::iterator iterator;
176 
177  MultiArrayNavigator(MULTI_ITERATOR const & i, shape_type const & shape, unsigned int inner_dimension)
178  : start_(), stop_(shape), point_(start_),
179  inner_dimension_(inner_dimension),
180  inner_shape_(stop_[inner_dimension] - start_[inner_dimension]),
181  i_(i + start_)
182  {
183  if(stop_[inner_dimension] > start_[inner_dimension])
184  stop_[inner_dimension] = start_[inner_dimension] + 1;
185  }
186 
187  MultiArrayNavigator(MULTI_ITERATOR const & i, shape_type const & start, shape_type const & stop,
188  unsigned int inner_dimension)
189  : start_(start), stop_(stop), point_(start_),
190  inner_dimension_(inner_dimension),
191  inner_shape_(stop_[inner_dimension] - start_[inner_dimension]),
192  i_(i + start_)
193  {
194  if(stop_[inner_dimension] > start_[inner_dimension])
195  stop_[inner_dimension] = start_[inner_dimension] + 1;
196  }
197 
198  void operator++()
199  {
200  ++point_[level];
201  ++i_.template dim<level>();
202  }
203 
204  void operator++(int)
205  {
206  ++*this;
207  }
208 
209  iterator begin() const
210  {
211  return i_.iteratorForDimension(inner_dimension_);
212  }
213 
214  iterator end() const
215  {
216  return begin() + inner_shape_;
217  }
218 
219  bool hasMore() const
220  {
221  return point_[level] < stop_[level];
222  }
223 
224  bool atEnd() const
225  {
226  return point_[level] >= stop_[level];
227  }
228 
229  shape_type const & point() const
230  {
231  return point_;
232  }
233 
234  protected:
235  void reset()
236  {
237  point_[level] = start_[level];
238  i_.template dim<level>() -= (stop_[level] - start_[level]);
239  }
240 
241  shape_type start_, stop_, point_;
242  unsigned int inner_dimension_, inner_shape_;
243  MULTI_ITERATOR i_;
244 };
245 
246 /********************************************************/
247 /* */
248 /* MultiCoordinateNavigator */
249 /* */
250 /********************************************************/
251 
252 /** \brief A navigator that provides access to the 1D subranges of an
253  n-dimensional range given by an nD shape.
254 
255  This class works similarly to \ref MultiArrayNavigator, but instead of a
256  1-dimensional iterator pair, it returns a pair of shapes whose difference
257  specifies a 1-dimensional range along the desired dimension. That is, when
258  the navigator refers to dimension <tt>d</tt>, the difference between
259  <tt>end()</tt> and <tt>begin()</tt> is <tt>1</tt> along all dimensions
260  except <tt>d</tt>.
261 
262  The template parameters specifies the dimension of the shape.
263 
264  <b>Usage:</b>
265 
266  <b>\#include</b> <vigra/navigator.hxx>
267 
268  Namespace: vigra
269 
270  \code
271  typedef vigra::MultiArrayShape<3>::type Shape;
272  typedef vigra::MultiArray<3, int> Array;
273  typedef vigra::MultiCoordinateNavigator<3> Navigator;
274 
275  Array a(Shape(X, Y, Z));
276 
277  for(int d=0; d<3; ++d)
278  {
279  // create Navigator for dimension d
280  Navigator nav(a.shape(), d);
281 
282  // outer loop: move navigator to all starting points
283  // of 1D subsets that run parallel to coordinate axis d
284  for(; nav.hasMore(); ++nav)
285  {
286  // inner loop: linear iteration over current subset
287  // d == {0, 1, 2}: iterate along {x, y, z}-axis respectively
288  Shape point = nav.begin(), end = nav.end();
289  for(; point[d] != end[d]; ++point[d])
290  a[point] = 5;
291  }
292  }
293  \endcode
294 */
295 template <unsigned int Dimensions, unsigned int N = Dimensions>
297 #ifndef DOXYGEN // doxygen doesn't understand this inheritance
298 : public MultiCoordinateNavigator<Dimensions, N-1>
299 #endif
300 {
301  typedef MultiCoordinateNavigator<Dimensions, N-1> base_type;
302 
303  public:
304  enum { level = N-1 };
305 
306  /** The shape type for the given iterator type.
307  */
309 
310 
311  /** Construct navigator for multi-dimensional iterator <TT>i</TT>, array shape <TT>shape</TT>
312  and inner loop dimension <TT>inner_dimension</TT>.
313  */
314  MultiCoordinateNavigator(value_type const & shape, unsigned int inner_dimension)
315  : base_type(shape, inner_dimension)
316  {
317  this->end_[level] = (this->inner_dimension_ == level)
318  ? 1
319  : this->shape_[level];
320  }
321 
322  /** Advance to next starting location.
323  */
324  void operator++()
325  {
327  if(base_type::atEnd() && this->i_[level] < this->end_[level])
328  {
329  ++this->i_[level];
330  if(this->i_[level] < this->end_[level])
331  base_type::reset();
332  }
333  }
334 
335  /** Advance to next starting location.
336  */
337  void operator++(int)
338  {
339  ++*this;
340  }
341 
342  /** true if there are more elements.
343  */
344  bool hasMore() const
345  {
346  return this->inner_dimension_ == level
347  ? base_type::hasMore()
348  : this->i_[level] < this->end_[level];
349  }
350 
351  /** true if iterator is exhausted.
352  */
353  bool atEnd() const
354  {
355  return !hasMore();
356  // return this->inner_dimension_ == level
357  // ? base_type::atEnd()
358  // : !(this->i_[level] < this->end_[level]);
359  }
360 
361  protected:
362  void reset()
363  {
364  this->i_[level] = 0;
365  this->end_[level] = (this->inner_dimension_ == level)
366  ? 1
367  : this->shape_[level];
368  base_type::reset();
369  }
370 };
371 
372 template <unsigned int Dimensions>
373 class MultiCoordinateNavigator<Dimensions, 1>
374 {
375  public:
376  enum { level = 0 };
378 
379  MultiCoordinateNavigator(value_type const & shape, unsigned int inner_dimension)
380  : shape_(shape),
381  inner_dimension_(inner_dimension)
382  {
383  end_[level] = (inner_dimension_ == level)
384  ? 1
385  : shape_[level];
386  }
387 
388  void operator++()
389  {
390  ++i_[level];
391  }
392 
393  void operator++(int)
394  {
395  ++*this;
396  }
397 
398  value_type const & begin() const
399  {
400  return i_;
401  }
402 
403  value_type end() const
404  {
405  value_type res = i_ + value_type(MultiArrayIndex(1));
406  res[inner_dimension_] = shape_[inner_dimension_];
407  return res;
408  }
409 
410  bool hasMore() const
411  {
412  return i_[level] < end_[level];
413  }
414 
415  bool atEnd() const
416  {
417  return !hasMore();
418  }
419 
420  protected:
421  void reset()
422  {
423  i_[level] = 0;
424  end_[level] = (inner_dimension_ == level)
425  ? 1
426  : shape_[level];
427  }
428 
429  value_type shape_, i_, end_;
430  unsigned int inner_dimension_;
431 };
432 
433 } // namespace vigra
434 
435 #endif /* VIGRA_NAVIGATOR_HXX */
MULTI_ITERATOR::multi_difference_type shape_type
Definition: navigator.hxx:109
MULTI_ITERATOR::iterator iterator
Definition: navigator.hxx:113
bool hasMore() const
Definition: navigator.hxx:149
void operator++(int)
Definition: navigator.hxx:337
bool atEnd() const
Definition: navigator.hxx:353
std::ptrdiff_t MultiArrayIndex
Definition: multi_fwd.hxx:60
bool hasMore() const
Definition: navigator.hxx:344
MultiCoordinateNavigator(value_type const &shape, unsigned int inner_dimension)
Definition: navigator.hxx:314
void operator++()
Definition: navigator.hxx:129
Definition: multi_fwd.hxx:63
A navigator that provides access to the 1D subranges of an n-dimensional range given by a vigra::Mult...
Definition: navigator.hxx:97
void operator++(int)
Definition: navigator.hxx:142
TinyVector< MultiArrayIndex, N > type
Definition: multi_shape.hxx:272
MultiArrayNavigator(MULTI_ITERATOR const &i, shape_type const &shape, unsigned int inner_dimension)
Definition: navigator.hxx:118
void operator++()
Definition: navigator.hxx:324
A navigator that provides access to the 1D subranges of an n-dimensional range given by an nD shape...
Definition: navigator.hxx:296
MultiArrayShape< Dimensions >::type value_type
Definition: navigator.hxx:308
bool atEnd() const
Definition: navigator.hxx:156

© 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.11.1 (Fri May 19 2017)