Milena (Olena)  User documentation 2.0a Id
 All Classes Namespaces Functions Variables Typedefs Enumerator Groups Pages
Rd.hh
1 // Copyright (C) 2007, 2008, 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_MORPHO_RD_HH
27 # define MLN_MORPHO_RD_HH
28 
29 // FIXME: This file, as well its functions and classes, shall not
30 // contain capital letters.
31 
35 
36 # include <vector>
37 # include <mln/core/concept/image.hh>
38 # include <mln/core/concept/neighborhood.hh>
39 # include <mln/trait/value_.hh>
40 # include <mln/data/fill.hh>
41 # include <mln/data/compare.hh>
42 # include <mln/util/ord.hh>
43 
44 
45 namespace mln
46 {
47 
48  namespace morpho
49  {
50 
51  template <typename I, typename N>
52  I
53  Rd(const Image<I>& f, const Image<I>& g, const Neighborhood<N>& nbh);
54 
55 
56 # ifndef MLN_INCLUDE_ONLY
57 
58  namespace impl
59  {
60 
61  template <typename I>
62  inline
63  std::vector<unsigned> compute_histo(const I& ima)
64  {
65  std::vector<unsigned> h(256, 0);
66  mln_piter(I) p(ima.domain());
67  for_all(p)
68  ++h[ima(p)];
69  return h;
70  }
71 
72  template <typename I>
73  inline
74  std::vector<mln_psite(I)> histo_reverse_sort(const I& ima)
75  {
76  std::vector<unsigned> h = compute_histo(ima);
77  // preparing output data
78  std::vector<int> loc(256);
79  loc[255] = 0;
80  for (int l = 254; l >= 0; --l)
81  loc[l] = loc[l+1] + h[l+1];
82  std::vector<mln_psite(I)> vec(ima.domain().nsites());
83  // storing output data
84  mln_piter(I) p(ima.domain());
85  for_all(p)
86  vec[loc[ima(p)]++] = p;
87  return vec;
88  }
89 
90 
91  template <typename I, typename N>
92  struct Rd
93  {
94  typedef mln_psite(I) point;
95  typedef mln_value(I) value;
96 
97  // in:
98  const I& f;
99  const I& g;
100  const N& nbh;
101 
102  // out:
103  I o;
104 
105  // aux:
106  mln_ch_value(I, bool) is_proc;
107  mln_ch_value(I, point) parent;
108  std::vector<point> S;
109 
110  inline
111  Rd(const I& f, const I& g, const N& nbh)
112  : f(f), g(g), nbh(nbh),
113  o(f.domain()),
114  is_proc(f.domain()),
115  parent(f.domain())
116  {
117  // init
118  data::fill(o, f);
119  S = histo_reverse_sort(g);
120  data::fill(is_proc, false); // FIXME: rm
121 
122  // first pass
123  for (unsigned i = 0; i < S.size(); ++i)
124  {
125  point p = S[i];
126 
127  make_set(p);
128  mln_niter(N) n(nbh, p);
129  for_all(n)
130  {
131  if (f.domain().has(n))
132  assert(is_proc(n) == is_proc__(n, p));
133  if (f.has(n) && is_proc(n))
134  do_union(n, p);
135  }
136  is_proc(p) = true;
137  }
138 
139  // second pass
140  for (int i = S.size() - 1; i >= 0; --i)
141  {
142  point p = S[i];
143  if (parent(p) == p)
144  {
145  if (o(p) == mln_max(value))
146  o(p) = g(p);
147  else
148  o(p) = o(parent(p));
149  }
150  }
151 
152  }
153 
154  inline
155  bool is_proc__(const point& n, const point& p) const
156  {
157  return g(n) > g(p) || (g(n) == g(p) && util::ord_strict(point(n), p));
158  }
159 
160  inline
161  void make_set(const point& p)
162  {
163  parent(p) = p;
164  }
165 
166  inline
167  point find_root(const point& x)
168  {
169  if (parent(x) == x)
170  return x;
171  else
172  return parent(x) = find_root(parent(x));
173  }
174 
175  inline
176  bool equiv(const point& r, const point& p)
177  {
178  return g(r) == g(p) || g(p) >= o(r);
179  }
180 
181  inline
182  void do_union(const point& n, const point& p)
183  {
184  point r = find_root(n);
185  if (r != p)
186  {
187  if (equiv(r, p))
188  {
189  parent(r) = p;
190  if (o(r) > o(p))
191  o(p) = o(r); // increasing criterion
192  }
193  else
194  o(p) = mln_max(value);
195  }
196  }
197 
198  };
199 
200  } // end of namespace mln::morpho::impl
201 
202 
203  // facade
204 
205  template <typename I, typename N>
206  inline
207  I
208  Rd(const Image<I>& f, const Image<I>& g, const Neighborhood<N>& nbh)
209  {
210  assert(f <= g);
211  impl::Rd<I,N> run(exact(f), exact(g), exact(nbh));
212  return run.o;
213  }
214 
215 # endif // ! MLN_INCLUDE_ONLY
216 
217  } // end of namespace mln::morpho
218 
219 } // end of namespace mln
220 
221 
222 #endif // ! MLN_MORPHO_RD_HH