Milena (Olena)  User documentation 2.0a Id
 All Classes Namespaces Functions Variables Typedefs Enumerator Groups Pages
sorted.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_CANVAS_LABELING_SORTED_HH
27 # define MLN_CANVAS_LABELING_SORTED_HH
28 
32 
33 
34 # include <mln/core/concept/image.hh>
35 # include <mln/data/fill.hh>
36 # include <mln/literal/zero.hh>
37 # include <mln/extension/adjust_fill.hh>
38 
39 # include <mln/data/sort_psites.hh>
40 # include <mln/data/sort_offsets.hh>
41 
42 # include <mln/canvas/labeling/generic.hh>
43 # include <mln/canvas/labeling/internal/tests.hh>
44 # include <mln/canvas/labeling/internal/find_root_fastest.hh>
45 
46 
47 
48 namespace mln
49 {
50 
51  namespace canvas
52  {
53 
54  namespace labeling
55  {
56 
57  template <typename I, typename N, typename L, typename F>
58  inline
59  mln_ch_value(I, L)
60  sorted(const Image<I>& input, const Neighborhood<N>& nbh,
61  L& nlabels, F& functor, bool increasing);
62 
63 
64 # ifndef MLN_INCLUDE_ONLY
65 
66 
67  // Implementations.
68 
69  namespace impl
70  {
71 
72  // Fastest sorted version
73 
74  template <typename I, typename N, typename L,
75  typename S, typename F>
76  mln_ch_value(I, L)
77  sorted_fastest(const Image<I>& input_,
78  const Neighborhood<N>& nbh_, L& nlabels,
79  const S& s, F& f)
80  {
81  trace::entering("canvas::impl::labeling::sorted_fastest");
82 
83  // FIXME: Test?!
84 
85  const I& input = exact(input_);
86  const N& nbh = exact(nbh_);
87 
88  extension::adjust(input, nbh);
89 
90  // Local type.
91  typedef mln_psite(I) P;
92 
93  // Auxiliary data.
94  mln_ch_value(I, bool) deja_vu;
95  mln_ch_value(I, unsigned) parent;
96 
97  // Output.
98  mln_ch_value(I, L) output;
99  bool status;
100 
101  // Initialization.
102  {
103  initialize(deja_vu, input);
104  mln::data::fill(deja_vu, false);
105  extension::fill(deja_vu, false); // So that the extension is ignored.
106 
107  initialize(parent, input);
108 
109  initialize(output, input);
110  mln::data::fill(output, L(literal::zero));
111  nlabels = 0;
112 
113  f.init_(); // Client initialization.
114  }
115 
116  util::array<int> dp = offsets_wrt(input, nbh);
117  const unsigned n_nbhs = dp.nelements();
118 
119  const unsigned n_points = s.nelements();
120 
121  // First Pass.
122  {
123  for (int i = n_points - 1; i >=0; --i) // Backward.
124  {
125  unsigned p = s[i];
126  if (! f.handles_(p))
127  continue;
128 
129  // Make-Set.
130  parent.element(p) = p;
131  f.init_attr_(p);
132 
133  for (unsigned j = 0; j < n_nbhs; ++j)
134  {
135  unsigned n = p + dp[j];
136  if (! deja_vu.element(n))
137  continue;
138 
139  if (f.equiv_(n, p))
140  {
141  // Do-Union.
142  unsigned r = internal::find_root_fastest(parent, n);
143  if (r != p)
144  {
145  parent.element(r) = p;
146  f.merge_attr_(r, p);
147  }
148  }
149  else
150  f.do_no_union_(n, p);
151  }
152  deja_vu.element(p) = true;
153  }
154  }
155 
156  // Second Pass.
157  {
158  for (unsigned i = 0; i < n_points; ++i) // Forward.
159  {
160  unsigned p = s[i];
161  if (! f.handles_(p))
162  continue;
163 
164  if (parent.element(p) == p) // if p is root
165  {
166  if (f.labels_(p))
167  {
168  if (nlabels == mln_max(L))
169  {
170  status = false;
171  trace::warning("labeling aborted! Too many labels \
172  for this label type: nlabels > \
173  max(label_type).");
174  return output;
175  }
176  output.element(p) = ++nlabels;
177  }
178  }
179  else
180  output.element(p) = output.element(parent.element(p));
181  }
182  status = true;
183  }
184 
185  trace::exiting("canvas::impl::labeling::sorted_fastest");
186  return output;
187  }
188 
189  } // end of namespace mln::canvas::impl
190 
191 
192  // Dispatch.
193 
194  namespace internal
195  {
196 
197  template <typename I, typename N, typename L, typename F>
198  inline
199  mln_ch_value(I, L)
200  sorted_dispatch(metal::false_,
201  const Image<I>& input,
202  const Neighborhood<N>& nbh, L& nlabels,
203  F& functor, bool increasing)
204  {
205  p_array<mln_psite(I)> s =
206  increasing ?
209  return impl::generic::labeling(input, nbh, nlabels, s,
210  functor);
211  }
212 
213  template <typename I, typename N, typename L, typename F>
214  inline
215  mln_ch_value(I, L)
216  sorted_dispatch(metal::true_,
217  const Image<I>& input,
218  const Neighborhood<N>& nbh, L& nlabels,
219  F& functor, bool increasing)
220  {
221  util::array<unsigned> s =
222  increasing ?
224  data::sort_offsets_decreasing(input);
225  return impl::sorted_fastest(input, nbh, nlabels, s,
226  functor);
227  }
228 
229  template <typename I, typename N, typename L, typename F>
230  inline
231  mln_ch_value(I, L)
232  sorted_dispatch(const Image<I>& input,
233  const Neighborhood<N>& nbh, L& nlabels,
234  F& functor, bool increasing)
235  {
236  enum {
237  test = mlc_equal(mln_trait_image_speed(I),
238  trait::image::speed::fastest)::value
239  &&
240  mln_is_simple_neighborhood(N)::value
241  };
242  return sorted_dispatch(metal::bool_<test>(),
243  input, nbh, nlabels,
244  functor, increasing);
245  }
246 
247 
248  } // end of namespace mln::canvas::internal
249 
250 
251 
252  // Facades.
253 
254 
255  template <typename I, typename N, typename L, typename F>
256  inline
257  mln_ch_value(I, L)
258  sorted(const Image<I>& input, const Neighborhood<N>& nbh,
259  L& nlabels, F& functor, bool increasing)
260  {
261  trace::entering("canvas::labeling::sorted");
262 
263  internal::labeling_tests(input, nbh, nlabels, functor);
264 
265  mln_ch_value(I, L) output;
266  output = internal::sorted_dispatch(input, nbh, nlabels,
267  functor, increasing);
268 
269  trace::exiting("canvas::labeling::sorted");
270  return output;
271  }
272 
273 
274 # endif // ! MLN_INCLUDE_ONLY
275 
276  } // end of namespace mln::canvas::labeling
277 
278  } // end of namespace mln::canvas
279 
280 } // end of namespace mln
281 
282 
283 #endif // ! MLN_CANVAS_LABELING_SORTED_HH