Milena (Olena)  User documentation 2.0a Id
 All Classes Namespaces Functions Variables Typedefs Enumerator Groups Pages
by_dilation/union_find.hh
1 // Copyright (C) 2007, 2008, 2009, 2010 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_RECONSTRUCTION_BY_DILATION_UNION_FIND_HH
28 # define MLN_MORPHO_RECONSTRUCTION_BY_DILATION_UNION_FIND_HH
29 
30 # include <cstdlib>
31 
32 # include <iostream>
33 # include <vector>
34 
35 # include <mln/core/concept/image.hh>
36 # include <mln/core/concept/neighborhood.hh>
37 # include <mln/data/fill.hh>
38 # include <mln/data/compare.hh>
39 # include <mln/data/sort_psites.hh>
40 
41 
42 namespace mln
43 {
44 
45  namespace morpho
46  {
47 
48  namespace reconstruction
49  {
50 
51  namespace by_dilation
52  {
53 
54 
55  template <typename I, typename J, typename N>
56  mln_concrete(I)
57  union_find(const Image<I>& f, const Image<J>& g,
58  const Neighborhood<N>& nbh);
59 
60 
61 # ifndef MLN_INCLUDE_ONLY
62 
63 
64  // Tests.
65 
66  namespace internal
67  {
68 
69  template <typename I, typename J, typename N>
70  inline
71  void
72  union_find_tests(const Image<I>& f_, const Image<J>& g_,
73  const Neighborhood<N>& nbh_)
74  {
75  const I& f = exact(f_);
76  const J& g = exact(g_);
77  const N& nbh = exact(nbh_);
78 
79  mln_precondition(f.is_valid());
80  mln_precondition(g.is_valid());
81  mln_precondition(nbh.is_valid());
82 
83  mln_precondition(f.domain() == g.domain()); // FIXME: Relax?
84  mln_precondition(f <= g);
85 
86  // mlc_equal(mln_value(I), mln_value(J))::check(); // FIXME: Too strong!
87  // FIXME: Also check that we have a total ordering for values.
88 
89  (void) f;
90  (void) g;
91  (void) nbh;
92  }
93 
94 
95 
96  template <typename Par>
97  inline
98  mln_site(Par) find_root(Par& parent, mln_site(Par) x)
99  {
100  if (parent(x) == x)
101  return x;
102  else
103  return parent(x) = find_root(parent, parent(x));
104  }
105 
106 
107  } // end of namespace mln::morpho::reconstruction::by_dilation::internal
108 
109 
110  // Implementations.
111 
112  namespace impl
113  {
114 
115  namespace generic
116  {
117 
118  template <typename I, typename J, typename N>
119  inline
120  mln_concrete(I)
121  union_find(const Image<I>& f_, const Image<J>& g_,
122  const Neighborhood<N>& nbh_)
123  {
124  trace::entering("morpho::reconstruction::by_dilation::impl::generic::union_find");
125 
126  const I& f = exact(f_);
127  const J& g = exact(g_);
128  const N& nbh = exact(nbh_);
129 
130  internal::union_find_tests(f, g, nbh);
131 
132 
133  typedef mln_site(I) P;
134  typedef mln_value(I) V;
135 
136  // Auxiliary data.
137  p_array<P> s;
138  mln_ch_value(I, bool) deja_vu;
139  mln_ch_value(I, P) parent;
140  mln_concrete(I) output;
141 
142  // Initialization.
143  {
144  initialize(output, f);
145  data::fill(output, f);
146  initialize(parent, f);
147  initialize(deja_vu, f);
148  data::fill(deja_vu, false);
149 
151  }
152 
153  // First pass.
154  {
155  for (unsigned i = 0; i < s.nsites(); ++i)
156  {
157  P p = s[i];
158  parent(p) = p; // Make-Set.
159  mln_niter(N) n(nbh, p);
160  for_all(n)
161  {
162 // if (f.domain().has(n))
163 // mln_invariant(deja_vu(n)
164 // ==
165 // (g(n) > g(p) || (g(n) == g(p)
166 // && util::ord_strict(n, p))));
167  if (f.domain().has(n) && deja_vu(n))
168  {
169  // Do-Union.
170  P r = internal::find_root(parent, n);
171  if (r != p)
172  {
173  if (g(r) == g(p) || g(p) >= output(r)) // Equivalence test.
174  {
175  parent(r) = p;
176  if (output(r) > output(p))
177  output(p) = output(r); // Increasing criterion.
178  }
179  else
180  output(p) = mln_max(V);
181  }
182  }
183  }
184  deja_vu(p) = true;
185  }
186  }
187 
188  // Second pass.
189  {
190  for (int i = s.nsites() - 1; i >= 0; --i)
191  {
192  P p = s[i];
193  if (parent(p) == p)
194  {
195  if (output(p) == mln_max(V))
196  output(p) = g(p);
197  }
198  else
199  output(p) = output(parent(p));
200  }
201  }
202 
203  mln_postcondition(output >= f);
204  mln_postcondition(output <= g);
205 
206  trace::exiting("morpho::reconstruction::by_dilation::impl::generic::union_find");
207  return output;
208  }
209 
210 
211  } // end of namespace mln::morpho::reconstruction::by_dilation::impl::generic
212 
213  } // end of namespace mln::morpho::reconstruction::by_dilation::impl
214 
215 
216  // Dispatch.
217 
218  namespace internal
219  {
220 
221  template <typename I, typename J, typename N>
222  inline
223  mln_concrete(I)
224  union_find_dispatch(trait::image::kind::logic,
225  const Image<I>& f, const Image<J>& g,
226  const Neighborhood<N>& nbh)
227  {
228  (void) f;
229  (void) g;
230  (void) nbh;
231 
232  // FIXME: Not yet implemented.
233  std::cerr
234  << __FILE__ << ":" << __LINE__ << ": error:\n"
235  "mln::morpho::reconstruction::by_dilation::internal::\n"
236  " union_find_dispatch(mln::trait::image::kind::logic,\n"
237  " const mln::Image<I>&,\n"
238  " const mln::Image<J>&,\n"
239  " const mln::Neighborhood<N>&)\n"
240  "not implemented."
241  << std::endl;
242  std::abort();
243  }
244 
245  template <typename I, typename J, typename N>
246  inline
247  mln_concrete(I)
248  union_find_dispatch(trait::image::kind::any,
249  const Image<I>& f, const Image<J>& g,
250  const Neighborhood<N>& nbh)
251  {
252  return impl::generic::union_find(f, g, nbh);
253  }
254 
255  template <typename I, typename J, typename N>
256  inline
257  mln_concrete(I)
258  union_find_dispatch(const Image<I>& f, const Image<J>& g,
259  const Neighborhood<N>& nbh)
260  {
261  return union_find_dispatch(mln_trait_image_kind(I)(),
262  f, g, nbh);
263  }
264 
265  } // end of namespace mln::morpho::reconstruction::by_dilation::internal
266 
267 
268  // Facade.
269 
270  template <typename I, typename J, typename N>
271  inline
272  mln_concrete(I)
273  union_find(const Image<I>& f, const Image<J>& g,
274  const Neighborhood<N>& nbh)
275  {
276  trace::entering("morpho::reconstruction::by_dilation::union_find");
277 
278  internal::union_find_tests(f, g, nbh);
279 
280  mln_concrete(I) output;
281  output = internal::union_find_dispatch(f, g, nbh);
282 
283  trace::exiting("morpho::reconstruction::by_dilation::union_find");
284  return output;
285  }
286 
287 # endif // ! MLN_INCLUDE_ONLY
288 
289  } // end of namespace mln::morpho::reconstruction::by_dilation
290 
291  } // end of namespace mln::morpho::reconstruction
292 
293  } // end of namespace mln::morpho
294 
295 } // end of namespace mln
296 
297 
298 #endif // ! MLN_MORPHO_RECONSTRUCTION_BY_DILATION_UNION_FIND_HH