Milena (Olena)  User documentation 2.0a Id
 All Classes Namespaces Functions Variables Typedefs Enumerator Groups Pages
adj_m_face_iter.hh
1 // Copyright (C) 2008, 2009 EPITA Research and Development Laboratory (LRDE)
2 //
3 // This file is part of Olena.
4 //
5 // Olena is free software: you can redistribute it and/or modify it under
6 // the terms of the GNU General Public License as published by the Free
7 // Software Foundation, version 2 of the License.
8 //
9 // Olena is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with Olena. If not, see <http://www.gnu.org/licenses/>.
16 //
17 // As a special exception, you may use this file as part of a free
18 // software project without restriction. Specifically, if other files
19 // instantiate templates or use macros or inline functions from this
20 // file, or you compile this file and link it with other files to produce
21 // an executable, this file does not by itself cause the resulting
22 // executable to be covered by the GNU General Public License. This
23 // exception does not however invalidate any other reasons why the
24 // executable file might be covered by the GNU General Public License.
25 
26 #ifndef MLN_TOPO_ADJ_M_FACE_ITER_HH
27 # define MLN_TOPO_ADJ_M_FACE_ITER_HH
28 
34 
35 # include <set>
36 # include <vector>
37 
38 # include <mln/topo/internal/complex_relative_iterator_base.hh>
39 # include <mln/topo/face.hh>
40 
41 
42 namespace mln
43 {
44 
45  namespace topo
46  {
47 
48  // Forward declarations.
49  template <unsigned D> class complex;
50  namespace internal
51  {
52  template <unsigned D> class adj_m_face_iterator;
53  }
54 
55 
56  /*-------------------------------.
57  | topo::adj_m_face_fwd_iter<D>. |
58  `-------------------------------*/
59 
69  template <unsigned D>
71  : public internal::forward_complex_relative_iterator_base< topo::face<D>,
72  algebraic_face<D>,
73  adj_m_face_fwd_iter<D> >,
74  public internal::adj_m_face_iterator<D>
75  {
76  // Tech note: we use topo::face to help g++-2.95.
77  private:
79  typedef internal::forward_complex_relative_iterator_base< topo::face<D>,
81  self_ > super_;
82  typedef internal::adj_m_face_iterator<D> impl_;
83 
84  public:
92  template <typename Fref>
93  adj_m_face_fwd_iter(const Fref& f_ref, unsigned m);
95 
100  void update_adj_faces_();
101  };
102 
103 
104  /*-------------------------------.
105  | topo::adj_m_face_bkd_iter<D>. |
106  `-------------------------------*/
107 
117  template <unsigned D>
119  : public internal::backward_complex_relative_iterator_base< topo::face<D>,
120  algebraic_face<D>,
121  adj_m_face_bkd_iter<D> >,
122  public internal::adj_m_face_iterator<D>
123  {
124  // Tech note: we use topo::face to help g++-2.95.
125  private:
127  typedef internal::backward_complex_relative_iterator_base< topo::face<D>,
129  self_ > super_;
130  typedef internal::adj_m_face_iterator<D> impl_;
131 
132  public:
140  template <typename Fref>
141  adj_m_face_bkd_iter(const Fref& f_ref, unsigned m);
143 
148  void update_adj_faces_();
149  };
150 
151 
152  /*-----------------------------------------.
153  | topo::internal::adj_m_face_iterator<D>. |
154  `-----------------------------------------*/
155 
156  namespace internal
157  {
158 
159  template <unsigned D>
160  class adj_m_face_iterator
161  {
162  protected:
163  adj_m_face_iterator();
164  adj_m_face_iterator(unsigned m);
165 
166  public:
168  unsigned m() const;
170  void set_m(unsigned m);
171 
172  protected:
175  void update_adj_faces__(const topo::face<D>& center,
176  std::vector< algebraic_face<D> >& adj_faces);
177 
179  unsigned m_;
180  };
181 
182  } // end of namespace mln::topo::internal
183 
184 
185 
186 # ifndef MLN_INCLUDE_ONLY
187 
188  /*-------------------------------.
189  | topo::adj_m_face_fwd_iter<D>. |
190  `-------------------------------*/
191 
192  template <unsigned D>
193  inline
195  {
196  }
197 
198  template <unsigned D>
199  template <typename Fref>
200  inline
201  adj_m_face_fwd_iter<D>::adj_m_face_fwd_iter(const Fref& f_ref, unsigned m)
202  : super_(f_ref), impl_(m)
203  {
204  }
205 
206  template <unsigned D>
207  inline
208  void
210  {
211  mln_precondition(this->c_);
212  // Delegate computation to base class.
213  this->update_adj_faces__(*this->c_, this->adj_faces_);
214  }
215 
216 
217  /*-------------------------------.
218  | topo::adj_m_face_bkd_iter<D>. |
219  `-------------------------------*/
220 
221  template <unsigned D>
222  inline
224  {
225  }
226 
227  template <unsigned D>
228  template <typename Fref>
229  inline
230  adj_m_face_bkd_iter<D>::adj_m_face_bkd_iter(const Fref& f_ref, unsigned m)
231  : super_(f_ref), impl_(m)
232  {
233  }
234 
235  template <unsigned D>
236  inline
237  void
239  {
240  mln_precondition(this->c_);
241  // Delegate computation to base class.
242  this->update_adj_faces__(*this->c_, this->adj_faces_);
243  }
244 
245 
246  /*-----------------------------------------.
247  | topo::internal::adj_m_face_iterator<D>. |
248  `-----------------------------------------*/
249 
250  namespace internal
251  {
252 
253  template <unsigned D>
254  inline
255  adj_m_face_iterator<D>::adj_m_face_iterator()
256  : m_(0)
257  {
258  }
259 
260  template <unsigned D>
261  inline
262  adj_m_face_iterator<D>::adj_m_face_iterator(unsigned m)
263  : m_(m)
264  {
265  mln_precondition(m <= D);
266  }
267 
268  template <unsigned D>
269  unsigned
270  adj_m_face_iterator<D>::m() const
271  {
272  return m_;
273  }
274 
275  template <unsigned D>
276  void
277  adj_m_face_iterator<D>::set_m(unsigned m)
278  {
279  m_ = m;
280  }
281 
282  template <unsigned D>
283  inline
284  void
285  adj_m_face_iterator<D>::update_adj_faces__(const topo::face<D>& center,
286  std::vector< algebraic_face<D> >& adj_faces)
287  {
288  adj_faces.clear();
289 
290  if (center.n() == m_)
291  return;
292 
293  typedef std::vector < topo::algebraic_face<D> > faces_t;
294  typedef std::set < topo::algebraic_face<D> > faces_set_t;
295 
296  /* FIXME: p_faces is redundant; we could use adj_faces
297  directly. */
298  /* The adjacent p-faces being built; initialized with CENTER,
299  and filled with q-faces at each step, until q reaches
300  m_. */
301  faces_t p_faces(1,
302  make_algebraic_face(center, true));
303  // The set of faces being built.
304  /* FIXME: This pattern is recurring in Milena---using an
305  std::set (or any fast associative container) to improve
306  the lookup speed of an std::vector; we should create a
307  class for this, a bit like mln::util::set, but with a
308  garantee on the order of insertion. */
309  faces_t work_faces;
310  faces_set_t work_faces_set;
311 
312  // Iteratively compute the set of locations.
313  for (unsigned p = center.n(); p != m_; (p < m_ ? ++p : --p) )
314  {
315  mln_invariant (p != m_);
316  for (typename faces_t::const_iterator g = p_faces.begin();
317  g != p_faces.end(); ++g)
318  {
319  mln_invariant (g->n() != m_);
320  faces_t q_faces = g->n() < m_ ?
321  g->higher_dim_adj_faces() :
322  g->lower_dim_adj_faces();
323  /* Traverse the higher- or lower-dimension adjacent
324  faces of G in the natural order if G's sign is
325  positive, or in the reverse order if G's sign is
326  negative. */
327  /* FIXME: Factor; the code if the two branches is the
328  same, except for the iteration order. */
329  if (g->sign())
330  {
331  for (typename faces_t::const_iterator h = q_faces.begin();
332  h != q_faces.end(); ++h)
333  // Don't insert a face twice.
334  if (work_faces_set.find(*h) == work_faces_set.end())
335  {
336  work_faces.push_back(*h);
337  work_faces_set.insert(*h);
338  }
339  }
340  else
341  {
342  for (typename faces_t::const_reverse_iterator h =
343  q_faces.rbegin();
344  /* This is crazy. With Apple g++ 4.0, this
345  code won't compile without this cast!
346  This is solved in MacPorts g++ 4.3. */
347  h != (typename faces_t::const_reverse_iterator) q_faces.rend();
348  ++h)
349  // Don't insert a face twice.
350  if (work_faces_set.find(*h) == work_faces_set.end())
351  {
352  work_faces.push_back(*h);
353  work_faces_set.insert(*h);
354  }
355  }
356  }
357  work_faces.swap(p_faces);
358  work_faces.clear();
359  work_faces_set.clear();
360  }
361 
362  adj_faces = p_faces;
363  }
364 
365  } // end of namespace mln::topo::internal
366 
367 # endif // ! MLN_INCLUDE_ONLY
368 
369  } // end of namespace mln::topo
370 
371 } // end of namespace mln
372 
373 #endif // ! MLN_TOPO_ADJ_M_FACE_ITER_HH