$extrastylesheet
Olena  User documentation 2.1
An Image Processing Platform
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
is_simple_cell.hh
1 // Copyright (C) 2009, 2010, 2011 EPITA Research and Development
2 // Laboratory (LRDE)
3 //
4 // This file is part of Olena.
5 //
6 // Olena is free software: you can redistribute it and/or modify it under
7 // the terms of the GNU General Public License as published by the Free
8 // Software Foundation, version 2 of the License.
9 //
10 // Olena is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with Olena. If not, see <http://www.gnu.org/licenses/>.
17 //
18 // As a special exception, you may use this file as part of a free
19 // software project without restriction. Specifically, if other files
20 // instantiate templates or use macros or inline functions from this
21 // file, or you compile this file and link it with other files to produce
22 // an executable, this file does not by itself cause the resulting
23 // executable to be covered by the GNU General Public License. This
24 // exception does not however invalidate any other reasons why the
25 // executable file might be covered by the GNU General Public License.
26 
27 #ifndef MLN_TOPO_IS_SIMPLE_CELL_HH
28 # define MLN_TOPO_IS_SIMPLE_CELL_HH
29 
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 
38 # include <mln/topo/is_facet.hh>
39 # include <mln/make/attachment.hh>
40 
41 
42 // FIXME: Have the functor take N, NL and NH neighborhood objects at
43 // the construction (instead of building them in operator()), as in
44 // does is_simple_pair.
45 
46 namespace mln
47 {
48 
49  namespace topo
50  {
51 
52  /* FIXME: Maybe we could add traits to deduce N from NL and NH (or
53  the converse). Anyway, the part of the code where neighborhood
54  are used should be moved into another functor
55  (`is_collapsible', see below), thus pushing away this
56  issue. */
57 
71  template <typename I, typename N, typename NL, typename NH>
73  : public mln::Function_v2b< is_simple_cell<I, N, NL, NH> >
74  {
75  public:
77  typedef bool result;
78 
80  is_simple_cell(const mln::Image<I>& ima);
81 
82  /* FIXME: Rename as init() or something like this? See how other
83  functors are written. */
85  void set_image(const mln::Image<I>& ima);
86 
93  /* FIXME: We probably broke the compatiblity with g++ 3.3, as it
94  seems this compiler does not like an indirect type like the
95  one of the following operator's argument. Check and possibly
96  improve this. */
97  bool operator()(const mln_psite(I)& p) const;
98 
99  private:
100  const I* ima_;
101  };
102 
103 
104 
105 # ifndef MLN_INCLUDE_ONLY
106 
107  template <typename I, typename N, typename NL, typename NH>
108  inline
110  : ima_(0)
111  {
112  mlc_equal(mln_value(I), bool)::check();
113  }
114 
115  template <typename I, typename N, typename NL, typename NH>
116  inline
118  : ima_(exact(&ima))
119  {
120  mlc_equal(mln_value(I), bool)::check();
121  }
122 
123  template <typename I, typename N, typename NL, typename NH>
124  inline
125  void
127  {
128  ima_ = exact(&ima);
129  }
130 
131  template <typename I, typename N, typename NL, typename NH>
132  inline
133  bool
134  is_simple_cell<I, N, NL, NH>::operator()(const mln_psite(I)& p) const
135  {
136  mln_precondition(ima_);
137  // Shortcut.
138  // FIXME: Introduce an `ima()' accessor instead?
139  const I& ima = *ima_;
140 
141  // The cell corresponding to P cannot be simple unless P is
142  // facet.
143  {
144  NH higher_adj_nbh;
145  if (!is_facet(ima, p, higher_adj_nbh))
146  return false;
147  }
148 
149  typedef p_set<mln_psite(I)> faces_t;
150 
151  // Compute the attachment of the cell corresponding to P to the
152  // domain of IMA.
153  N adj_nbh;
154  faces_t att = make::attachment(ima, p, adj_nbh);
155 
156  // A cell with an empty attachment is not simple.
157  /* FIXME: Why p_set does not provide an empty() predicate? */
158  if (att.nsites() == 0)
159  return false;
160 
161  /* FIXME: This part could be moved to its own function/method
162  (`is_collapsible'). Moreover, the code could be split: looking
163  up for a free pair (g, h) could be performed in another
164  routine. */
165  // Try to collapse the attachment (to a single point).
166  {
167  NL lower_adj_nbh;
168  NH higher_adj_nbh;
169  while (att.nsites() > 1)
170  {
171 
172  bool simple_pair_collapsed = false;
173  /* FIXME: The selection of G and H is probably suboptimal
174  (i.e., selecting G has a face of highest avalaible
175  dimension in CELL is probably smarter). */
176  mln_piter(faces_t) g(att);
177  for_all(g)
178  /* G cannot have dimension 0, since we later look for an
179  adjacent face H of lower dimension. */
180  if (static_cast<mln_psite(I)>(g).n() > 0)
181  {
182  // Check whether G is a facet within ATT.
183  bool g_is_facet = true;
184  mln_niter(NH) f(higher_adj_nbh, g);
185  for_all(f)
186  if (att.has(f))
187  {
188  g_is_facet = false;
189  break;
190  }
191  if (!g_is_facet)
192  break;
193 
194  // Look for a face H stricly included in G.
195  bool gh_is_simple_pair = false;
196  mln_niter(NL) h(lower_adj_nbh, g);
197  for_all(h)
198  {
199  bool h_strictly_in_g = true;
200  if (att.has(h))
201  {
202  mln_niter(NH) i(higher_adj_nbh, h);
203  for_all(i)
204  if (i != g && att.has(i))
205  {
206  h_strictly_in_g = false;
207  break;
208  }
209  }
210  if (h_strictly_in_g)
211  {
212  gh_is_simple_pair = true;
213  att.remove(g);
214  att.remove(h);
215  mln_invariant(att.nsites() > 0);
216  break;
217  }
218  } // for_all(h)
219 
220  // If a free pair (G, H) has been found and removed,
221  // restart the free pair look up from the beginning.
222  if (gh_is_simple_pair)
223  {
224  simple_pair_collapsed = true;
225  break;
226  }
227  } // for_all(g)
228 
229  if (!simple_pair_collapsed)
230  // If no free pair (G, H) was found, then the attachment is
231  // not collapsible.
232  return false;
233 
234  } // while (att.nsites() > 1)
235 
236  mln_postcondition(att.nsites() == 1);
237  mln_postcondition(att[0].n() == 0);
238  // If the attachment is collapsible to a 0-face, then the cell
239  // corresponding to the (face) P is simple.
240  return true;
241  }
242  }
243 
244 # endif // MLN_INCLUDE_ONLY
245 
246  } // end of namespace mln::topo
247 
248 } // end of namespace mln
249 
250 #endif // ! MLN_TOPO_IS_SIMPLE_CELL_HH