Milena (Olena)  User documentation 2.0a Id
 All Classes Namespaces Functions Variables Typedefs Enumerator Groups Pages
is_simple_cell.hh
1 // Copyright (C) 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_IS_SIMPLE_CELL_HH
27 # define MLN_TOPO_IS_SIMPLE_CELL_HH
28 
32 
33 # include <mln/core/concept/function.hh>
34 # include <mln/core/concept/image.hh>
35 
36 # include <mln/core/site_set/p_set.hh>
37 # include <mln/core/site_set/complex_psite.hh>
38 # include <mln/core/site_set/p_complex_piter.hh>
39 # include <mln/core/image/complex_neighborhoods.hh>
40 # include <mln/core/image/complex_neighborhood_piter.hh>
41 
42 # include <mln/make/attachment.hh>
43 
44 
45 namespace mln
46 {
47 
48  namespace topo
49  {
50 
56  template <typename I>
57  class is_simple_cell : public mln::Function_v2b< is_simple_cell<I> >
58  {
59  public:
61  static const unsigned D = I::dim;
63  typedef mln_geom(I) G;
65  typedef mln::complex_psite<D, G> psite;
66 
68  typedef bool result;
69 
71  is_simple_cell(const mln::Image<I>& ima);
72 
73  /* FIXME: Rename as init() or something like this? See how other
74  functors are written. */
76  void set_image(const mln::Image<I>& ima);
77 
79  bool operator()(const mln::complex_psite<I::dim,mln_geom(I)>& p) const;
80  // Tech note: The argument type above is explicit to help g++-3.3.
81 
82  private:
83  const I* ima_;
84  };
85 
86 
87 
88 # ifndef MLN_INCLUDE_ONLY
89 
90  template <typename I>
91  inline
93  : ima_(0)
94  {
95  }
96 
97  template <typename I>
98  inline
100  : ima_(mln::exact(&ima))
101  {
102  }
103 
104  template <typename I>
105  inline
106  void
108  {
109  ima_ = mln::exact(&ima);
110  }
111 
112  template <typename I>
113  inline
114  bool
115  is_simple_cell<I>::operator()(const mln::complex_psite<I::dim,mln_geom(I)>& p) const
116  // Tech note: The argument type above is explicit to help g++-3.3.
117  {
118  mln_precondition(ima_);
119 
120  typedef p_set<psite> faces_t;
121 
122  // Compute the attachment of the cell corresponding to P to he
123  // domain of *IMA_.
124  faces_t att = make::attachment(p, *ima_);
125 
126  // A cell with an empty attachment is not simple.
127  /* FIXME: Why does p_set not provide an empty() predicate? */
128  if (att.nsites() == 0)
129  return false;
130 
131  /* FIXME: This part could be moved to its own function/method
132  (`is_collapsible'). Moreover, the code could be split: looking
133  up for a free pair (g, h) could be performed in another
134  routine. */
135  // Try to collapse the attachment (to a single point).
136  {
137  typedef complex_lower_neighborhood<D, G> lower_adj_nbh_t;
138  typedef complex_higher_neighborhood<D, G> higher_adj_nbh_t;
139  lower_adj_nbh_t lower_adj_nbh;
140  higher_adj_nbh_t higher_adj_nbh;
141  while (att.nsites() > 1)
142  {
143 
144  bool simple_pair_collapsed = false;
145  /* FIXME: The selection of G and H is probably suboptimal
146  (i.e., selecting G has a face of highest avalaible
147  dimension in CELL is probably smarter). */
148  mln_piter(faces_t) g(att);
149  for_all(g)
150  /* G cannot have dimension 0, since we later look for an
151  adjacent face H of lower dimension. */
152  if (static_cast<psite>(g).n() > 0)
153  {
154  // Check whether G is a facet within ATT.
155  bool g_is_facet = true;
156  mln_niter(higher_adj_nbh_t) f(higher_adj_nbh, g);
157  for_all(f)
158  if (att.has(f))
159  {
160  g_is_facet = false;
161  break;
162  }
163  if (!g_is_facet)
164  break;
165 
166  // Look for a face H stricly included in G.
167  bool gh_is_simple_pair = false;
168  mln_niter(lower_adj_nbh_t) h(lower_adj_nbh, g);
169  for_all(h)
170  {
171  bool h_strictly_in_g = true;
172  if (att.has(h))
173  {
174  mln_niter(higher_adj_nbh_t) i(higher_adj_nbh, h);
175  for_all(i)
176  if (i != g && att.has(i))
177  {
178  h_strictly_in_g = false;
179  break;
180  }
181  }
182  if (h_strictly_in_g)
183  {
184  gh_is_simple_pair = true;
185  att.remove(g);
186  att.remove(h);
187  mln_invariant(att.nsites() > 0);
188  break;
189  }
190  } // for_all(h)
191 
192  // If a free pair (G, H) has been found and removed,
193  // restart the free pair look up from the beginning.
194  if (gh_is_simple_pair)
195  {
196  simple_pair_collapsed = true;
197  break;
198  }
199  } // for_all(g)
200 
201  if (!simple_pair_collapsed)
202  // If no free pair (G, H) was found, then the attachment is
203  // not collapsible.
204  return false;
205 
206  } // while (att.nsites() > 1)
207 
208  mln_postcondition(att.nsites() == 1);
209  mln_postcondition(att[0].n() == 0);
210  // If the attachment is collapsible to a 0-face, then the cell
211  // corresponding to the (face) P is simple.
212  return true;
213  }
214  }
215 
216 # endif // MLN_INCLUDE_ONLY
217 
218  } // end of namespace mln::topo
219 
220 } // end of namespace mln
221 
222 #endif // ! MLN_TOPO_IS_SIMPLE_CELL_HH