$extrastylesheet
Olena  User documentation 2.1
An Image Processing Platform
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
dual_union_find.hh
1 // Copyright (C) 2008, 2009, 2013 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_MORPHO_TREE_IMLP_DUAL_UNION_FIND_HH
28 # define MLN_MORPHO_TREE_IMLP_DUAL_UNION_FIND_HH
29 
41 
42 # include <mln/data/fill.hh>
43 
44 # include <mln/geom/nsites.hh>
45 # include <mln/geom/translate.hh>
46 
47 # include <mln/morpho/tree/data.hh>
48 
49 # include <mln/util/timer.hh>
50 
51 namespace mln
52 {
53 
54  namespace morpho
55  {
56 
57  namespace tree
58  {
59 
60  namespace impl
61  {
62 
63  namespace generic
64  {
65 
76  template <typename I, typename S, typename N>
78  dual_union_find(const Image<I>& f,
79  const Image<I>& m,
80  const Site_Set<S>& s_f,
81  const Site_Set<S>& s_m,
82  const Neighborhood<N>& nbh);
83 
84  } // end of namespace mln::morpho::tree::impl::generic
85 
86  } // end of namespace mln::morpho::tree::impl
87 
88 # ifndef MLN_INCLUDE_ONLY
89 
90  namespace internal
91  {
92  // For benchmark purpose. More than 50% of the time is spent
93  // in find_root function.
94  static util::timer t_prop;
95 
96 
97  template <typename I>
98  inline
99  mln_psite(I) find_root(I& zpar,
100  const mln_psite(I)& p)
101  {
102  if (zpar(p) == p)
103  return p;
104 
105  t_prop.resume();
106  mln_psite(I) x = zpar(p);
107  while (zpar(x) != x)
108  x = zpar(x);
109 
110  mln_psite(I) tmp;
111  for (mln_psite(I) y = p; y != x; y = tmp)
112  {
113  tmp = zpar(y);
114  zpar(y) = x;
115  }
116  t_prop.stop();
117 
118  return x;
119  }
120 
121  template <typename I>
122  inline
123  void
124  update_m_parent(const I& f,
125  mln_ch_value(I, mln_psite(I))& parent,
126  mln_ch_value(I, bool)& deja_vu,
127  p_array< mln_psite(I) >& sset,
128  const mln_domain(I)& d_ext,
129  const mln_psite(I)& p)
130  {
131  typedef mln_psite(I) P;
132 
133  P q = parent(p);
134  P x = parent(q);
135 
136  mln_assertion(d_ext.has(q));
137 
138  while (d_ext.has(x) && f(q) == f(x) && q != x)
139  {
140  q = x;
141  x = parent(q);
142  }
143 
144  if (!d_ext.has(x))
145  {
146  if (f(x) == f(parent(x)))
147  x = (parent(q) = parent(x));
148  if (f(q) != f(x))
149  {
150  x = q;
151  if (!deja_vu(q))
152  {
153  deja_vu(q) = true;
154  sset.append(q);
155  }
156  }
157 
158  }
159  else
160  {
161  if (x != q)
162  {
163  update_m_parent(f, parent, deja_vu, sset, d_ext, q);
164  x = q;
165  }
166  if (!deja_vu(q))
167  {
168  deja_vu(q) = true;
169  sset.append(q);
170  }
171  }
172 
173  for (P i = p, tmp = parent(i); i != q; i = tmp, tmp = parent(i))
174  parent(i) = x;
175  }
176 
177  } // end of namespace mln::morpho::tree::internal
178 
179  namespace impl
180  {
181 
182  namespace generic
183  {
184 
185 
186  template <typename I, typename S, typename N>
188  dual_union_find(const Image<I>& f_,
189  const Image<I>& m_,
190  const Site_Set<S>& s_f_,
191  const Site_Set<S>& s_m_,
192  const Neighborhood<N>& nbh_)
193  {
194  mln_trace("morpho::tree::impl::generic::dual_union_find");
195 
196  util::timer tm;
197  tm.start();
198  internal::t_prop.reset();
199 
200  typedef mln_psite(I) P;
201  typedef unsigned L;
202 
203  const I& f = exact(f_);
204  const I& m = exact(m_);
205  const S& s_f = exact(s_f_);
206  const S& s_m = exact(s_m_);
207  const N& nbh = exact(nbh_);
208 
209  // Aux data.
210  mln_psite(I)::delta dp(literal::zero);
211  mln_domain(I) d_f = f.domain();
212  mln_domain(I) d_ext = f.domain(); // translate dp
213  mln_domain(I) d = f.domain();
214 
215  // Extend the domain.
216  dp[0] = d.pmax()[0] - d.pmin()[0] + 1;
217  d.pmax() += dp;
218  d_ext.pmin() += dp;
219  d_ext.pmax() += dp;
220 
221  // Data.
222  mln_concrete(I) fext;
223  mln_ch_value(I, P) parent;
224  p_array<mln_psite(I)> s;
225 
226  // Initialization.
227  fext = geom::translate(m, dp.to_vec(), f, d);
228  initialize(parent, fext);
229  s.reserve(geom::nsites(fext));
230 
231  //Process
232  {
233  // Aux data.
234  mln_ch_value(I, bool) deja_vu;
235  mln_ch_value(I, P) zpar;
236 
237  initialize(deja_vu, fext);
238  initialize(zpar, fext);
239  mln::data::fill(deja_vu, false);
240 
241  mln_bkd_piter(S) p_f(s_f); // Backward.
242  mln_bkd_piter(S) p_m(s_m); // Backward.
243  p_f.start();
244  p_m.start();
245 
246  // Main loop.
247  while (p_m.is_valid() || p_f.is_valid())
248  {
249  mln_bkd_piter(S)& it = (!p_f.is_valid() || (p_m.is_valid() && f(p_f) <= m(p_m))) ? p_m : p_f;
250 
251  P p = it;
252  P ext = p + dp;
253 
254  mln_assertion(!(deja_vu(p) && deja_vu(ext)));
255  if (deja_vu(ext)) // Seen by mask before f.
256  {
257  mln_assertion(m(p) >= f(p));
258  // Make set.
259  parent(p) = p;
260  zpar(p) = p;
261 
262  P r = internal::find_root(zpar, ext);
263  zpar(r) = p;
264  parent(r) = p;
265 
266  deja_vu(p) = true;
267  }
268  else if (deja_vu(p)) // Seen by f before mask.
269  {
270  mln_assertion(f(p) > m(p));
271  parent(p) = ext;
272  zpar(p) = ext;
273  parent(ext) = ext;
274  zpar(ext) = ext;
275 
276  mln_niter(N) n(nbh, ext);
277  for_all(n)
278  if (d_ext.has(n) && deja_vu(n))
279  {
280  P r = internal::find_root(zpar, n);
281  if (r != ext)
282  {
283  parent(r) = ext;
284  zpar(r) = ext;
285  }
286  }
287  deja_vu(ext) = true;
288  }
289  else if (f(p) <= m(p)) // First time p encountered.
290  {
291  zpar(ext) = ext;
292  mln_niter(N) n(nbh, ext);
293  for_all(n)
294  if (d_ext.has(n) && deja_vu(n))
295  {
296  P r = internal::find_root(zpar, n);
297  if (r != ext)
298  {
299  zpar(r) = ext;
300  parent(r) = ext;
301  }
302  }
303  deja_vu(ext) = true;
304  }
305  else
306  {
307  deja_vu(p) = true;
308  }
309  it.next();
310  }
311  }
312  tm.restart();
313 
314  // Canonization
315  {
316  mln_ch_value(I, bool) deja_vu(d_ext);
317  mln::data::fill(deja_vu, false);
318  mln_fwd_piter(S) p(s_f); // Forward.
319  for_all(p)
320  {
321  P q = parent(p);
322  if (!f.domain().has(q))
323  internal::update_m_parent(fext, parent, deja_vu, s, d_ext, p);
324  else if (fext(parent(q)) == f(q))
325  parent(p) = parent(q);
326  s.append(p);
327 
328  mln_assertion((q = parent(p)) == parent(q) || fext(q) != fext(parent(q)));
329  }
330  }
331 
332  //mln_postcondition(internal::compute_parent_postconditions(fext, s, parent));
333 
334  tree::data<I, p_array<mln_psite(I)> > tree(fext, parent, s);
335 
336  return tree;
337  }
338 
339  } // end of namespace mln::morpho::tree::impl::generic
340 
341  } // end of namespace mln::morpho::tree::impl
342 
343 # endif // ! MLN_INCLUDE_ONLY
344 
345  } // end of namespace mln::morpho::tree
346 
347  } // end of namespace mln::morpho
348 
349 } // end of namespace mln
350 
351 #endif // !MLN_MORPHO_TREE_IMLP_DUAL_UNION_FIND_HH