$extrastylesheet
Olena  User documentation 2.1
An Image Processing Platform
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
canvas/distance_geodesic.hh
1 // Copyright (C) 2008, 2009, 2012 EPITA Research and Development Laboratory
2 // (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_CANVAS_DISTANCE_GEODESIC_HH
28 # define MLN_CANVAS_DISTANCE_GEODESIC_HH
29 
33 
34 # include <mln/core/concept/image.hh>
35 # include <mln/core/concept/neighborhood.hh>
36 # include <mln/core/routine/duplicate.hh>
37 
38 # include <mln/core/site_set/p_queue_fast.hh>
39 # include <queue>
40 
41 # include <mln/data/fill.hh>
42 # include <mln/extension/adjust_fill.hh>
43 
44 
45 namespace mln
46 {
47 
48  namespace canvas
49  {
50 
55  template <typename I, typename N, typename D,
56  typename F>
57  mln_ch_value(I, D)
58  distance_geodesic(const Image<I>& input, const Neighborhood<N>& nbh,
59  D max, F& functor);
60 
61 
62 
63 # ifndef MLN_INCLUDE_ONLY
64 
65 
66  // Tests.
67 
68  namespace internal
69  {
70 
71  template <typename I, typename N, typename D,
72  typename F>
73  void
74  distance_geodesic_tests(const Image<I>& input_,
75  const Neighborhood<N>& nbh_, D max,
76  F& functor)
77  {
78  const I& input = exact(input_);
79  const N& nbh = exact(nbh_);
80 
81  mln_precondition(input.is_valid());
82  mln_precondition(nbh.is_valid());
83 
84  (void) input;
85  (void) nbh;
86  (void) max;
87  (void) functor;
88  }
89 
90 
91  } // of namespace mln::canvas::internal
92 
93 
94 
95  // Implementations.
96 
97  namespace impl
98  {
99 
100  namespace generic
101  {
102 
103  template <typename I, typename N, typename D,
104  typename F>
105  mln_ch_value(I, D)
106  distance_geodesic(const Image<I>& input_, const Neighborhood<N>& nbh_,
107  D max, F& functor)
108  {
109  mln_trace("canvas::impl::generic::distance_geodesic");
110 
111  const I& input = exact(input_);
112  const N& nbh = exact(nbh_);
113 
114  internal::distance_geodesic_tests(input, nbh, max, functor);
115 
116  mln_precondition(input.is_valid());
117  mln_precondition(nbh.is_valid());
118 
119  mln_ch_value(I, D) dmap; // Distance map is aux data.
120  initialize(dmap, input);
121 
122  typedef mln_site(I) P;
123  p_queue_fast<P> q;
124 
125  // Initialization.
126  {
127  functor.init(input); // <-- init
128  data::fill(dmap, max);
129 
130  mln_piter(I) p(input.domain());
131  mln_niter(N) n(nbh, p);
132  for_all(p)
133  if (functor.inqueue_p_wrt_input_p(input(p))) // <-- inqueue_p_wrt_input_p
134  {
135  functor.init_p(p); // <-- init_p
136  dmap(p) = 0;
137  for_all(n)
138  if (input.domain().has(n) &&
139  functor.inqueue_p_wrt_input_n(input(n))) // <-- inqueue_p_wrt_input_n
140  {
141  q.push(p);
142  break;
143  }
144  }
145  }
146 
147  // Propagation.
148  {
149  P p;
150  mln_niter(N) n(nbh, p);
151  while (! q.is_empty())
152  {
153  p = q.pop_front();
154  if (dmap(p) == max)
155  {
156  // Saturation so stop.
157  q.clear();
158  break;
159  }
160  for_all(n)
161  if (input.domain().has(n) && dmap(n) == max)
162  {
163  dmap(n) = dmap(p) + 1;
164  functor.process(p, n); // <- process
165  q.push(n);
166  }
167  }
168  }
169 
170  return dmap;
171  }
172 
173  } // of namespace mln::canvas::impl::generic
174 
175 
176 
177  // Fastest version.
178 
179  template <typename I, typename N, typename D,
180  typename F>
181  mln_ch_value(I, D)
182  distance_geodesic_fastest(const Image<I>& input_,
183  const Neighborhood<N>& nbh_,
184  D max,
185  F& functor)
186  {
187  mln_trace("canvas::impl::distance_geodesic_fastest");
188 
189  const I& input = exact(input_);
190  const N& nbh = exact(nbh_);
191 
192  internal::distance_geodesic_tests(input, nbh, max, functor);
193 
194  extension::adjust(input, nbh);
195 
196  mln_ch_value(I, D) dmap; // Distance map is aux data.
197  initialize(dmap, input);
198 
199  std::queue<unsigned> q;
200 
201  // Initialization.
202  {
203  functor.init_(input); // <-- init
204  data::fill(dmap, max);
205  // For the extension to be ignored:
206  extension::fill(input, true);
207  extension::fill(dmap, D(0));
208 
209  mln_pixter(const I) p(input);
210  mln_nixter(const I, N) n(p, nbh);
211  for_all(p)
212  if (functor.inqueue_p_wrt_input_p_(p.val())) // <-- inqueue_p_wrt_input_p
213  {
214  functor.init_p_(p); // <-- init_p
215  dmap.element(p.offset()) = 0;
216  for_all(n)
217  if (functor.inqueue_p_wrt_input_n_(n.val())) // <-- inqueue_p_wrt_input_n
218  {
219  q.push(p.offset());
220  break;
221  }
222  }
223  }
224 
225  // Propagation.
226  {
227  unsigned p;
228 
229  util::array<int> dp = offsets_wrt(input, nbh);
230  const unsigned n_nbhs = dp.nelements();
231 
232  while (! q.empty())
233  {
234  p = q.front();
235  q.pop();
236  if (dmap.element(p) == max)
237  // Saturation so stop.
238  break;
239  for (unsigned i = 0; i < n_nbhs; ++i)
240  {
241  unsigned n = p + dp[i];
242  if (dmap.element(n) == max)
243  {
244  dmap.element(n) = dmap.element(p) + 1;
245  functor.process_(p, n); // <- process
246  q.push(n);
247  }
248  }
249  }
250  }
251 
252  return dmap;
253  }
254 
255 
256  } // of namespace mln::canvas::impl
257 
258 
259 
260  // Dispatch.
261 
262  namespace internal
263  {
264 
265  template <typename I, typename N, typename D,
266  typename F>
267  inline
268  mln_ch_value(I, D)
269  distance_geodesic_dispatch(metal::false_,
270  const Image<I>& input,
271  const Neighborhood<N>& nbh, D max,
272  F& functor)
273  {
274  return impl::generic::distance_geodesic(input, nbh, max,
275  functor);
276  }
277 
278  template <typename I, typename N, typename D,
279  typename F>
280  inline
281  mln_ch_value(I, D)
282  distance_geodesic_dispatch(metal::true_,
283  const Image<I>& input,
284  const Neighborhood<N>& nbh, D max,
285  F& functor)
286  {
287  return impl::distance_geodesic_fastest(input, nbh, max, functor);
288 // return impl::generic::distance_geodesic(input, nbh, max,
289 // functor);
290  }
291 
292  template <typename I, typename N, typename D,
293  typename F>
294  inline
295  mln_ch_value(I, D)
296  distance_geodesic_dispatch(const Image<I>& input,
297  const Neighborhood<N>& nbh, D max,
298  F& functor)
299  {
300  enum {
301  test = mlc_equal(mln_trait_image_speed(I),
302  trait::image::speed::fastest)::value
303  &&
304  mln_is_simple_neighborhood(N)::value
305  };
306  return distance_geodesic_dispatch(metal::bool_<test>(),
307  input, nbh, max,
308  functor);
309  }
310 
311 
312  } // of namespace mln::canvas::internal
313 
314 
315 
316  // Facade.
317 
318  template <typename I, typename N, typename D,
319  typename F>
320  inline
321  mln_ch_value(I, D)
322  distance_geodesic(const Image<I>& input, const Neighborhood<N>& nbh,
323  D max, F& functor)
324  {
325  mln_trace("canvas::distance_geodesic");
326 
327  internal::distance_geodesic_tests(input, nbh, max, functor);
328 
329  mln_ch_value(I,D) output;
330  output = internal::distance_geodesic_dispatch(input, nbh, max, functor);
331 
332  return output;
333  }
334 
335 
336 # endif // ! MLN_INCLUDE_ONLY
337 
338  } // end of namespace mln::canvas
339 
340 } // end of namespace mln
341 
342 
343 #endif // ! MLN_CANVAS_DISTANCE_GEODESIC_HH