26 #ifndef MLN_CANVAS_DISTANCE_FRONT_HH
27 # define MLN_CANVAS_DISTANCE_FRONT_HH
34 # include <mln/core/concept/image.hh>
35 # include <mln/core/concept/neighborhood.hh>
36 # include <mln/core/concept/weighted_window.hh>
37 # include <mln/data/fill.hh>
38 # include <mln/accu/stat/max.hh>
39 # include <mln/extension/adjust_fill.hh>
50 typename N,
typename W,
typename D,
54 const Neighborhood<N>& nbh, const Weighted_Window<W>& w_win, D max,
59 # ifndef MLN_INCLUDE_ONLY
68 typename N,
typename W,
typename D,
71 distance_front_tests(
const Image<I>& input_,
72 const Neighborhood<N>& nbh_,
73 const Weighted_Window<W>& w_win_,
77 const I& input = exact(input_);
78 const N& nbh = exact(nbh_);
79 const W& w_win = exact(w_win_);
81 mln_precondition(input.is_valid());
82 mln_precondition(nbh.is_valid());
104 template <
typename I,
105 typename N,
typename W,
typename D,
109 const Neighborhood<N>& nbh_,
110 const Weighted_Window<W>& w_win_,
114 trace::entering(
"canvas::impl::generic::distance_front");
116 const I& input = exact(input_);
117 const N& nbh = exact(nbh_);
118 const W& w_win = exact(w_win_);
120 mln_precondition(input.is_valid());
121 mln_precondition(w_win.is_valid());
123 typedef mln_site(I) P;
124 typedef std::vector<P> bucket_t;
127 mln_ch_value(I, D) dmap;
129 data::fill(dmap, max);
134 accu::stat::max<unsigned> m;
135 for (
unsigned i = 0; i < w_win.size(); ++i)
137 mod = unsigned(m) + 1;
141 std::vector<bucket_t> bucket(mod);
142 unsigned bucket_size = 0;
147 mln_piter(I) p(input.domain());
148 mln_niter(N) n(nbh, p);
150 if (functor.inqueue_p_wrt_input_p(input(p)))
154 if (input.domain().has(n) &&
155 functor.inqueue_p_wrt_input_n(input(n)))
157 bucket[0].push_back(p);
167 mln_qiter(W) q(w_win, p);
168 for (
unsigned d = 0; bucket_size != 0; ++d)
170 bucket_t& bucket_d = bucket[d % mod];
171 for (
unsigned i = 0; i < bucket_d.size(); ++i)
178 bucket_size = bucket_d.size();
187 if (dmap.domain().has(q) && dmap(q) > d)
189 unsigned d_ = d + q.w();
193 functor.process(p, q);
194 bucket[d_ % mod].push_back(q);
199 bucket_size -= bucket_d.size();
204 trace::exiting(
"canvas::impl::generic::distance_front");
214 template <
typename I,
215 typename N,
typename W,
typename D,
218 distance_front_fastest(const Image<I>& input_,
219 const Neighborhood<N>& nbh_,
220 const Weighted_Window<W>& w_win_,
223 trace::entering(
"canvas::impl::distance_front_fastest");
225 const I& input = exact(input_);
226 const N& nbh = exact(nbh_);
227 const W& w_win = exact(w_win_);
229 mln_precondition(input.is_valid());
230 mln_precondition(w_win.is_valid());
234 const unsigned n_ws = w_win.size();
235 util::array<int> dp = offsets_wrt(input, w_win.win());
236 mln_invariant(dp.nelements() == n_ws);
239 mln_ch_value(I, D) dmap;
241 data::fill(dmap, max);
246 accu::stat::max<unsigned> m;
247 for (
unsigned i = 0; i < w_win.size(); ++i)
249 mod = unsigned(m) + 1;
253 typedef std::vector<unsigned> bucket_t;
254 std::vector<bucket_t> bucket(mod);
255 unsigned bucket_size = 0;
259 functor.init_(input);
265 mln_pixter(
const I) p(input);
266 mln_nixter(const I, N) n(p, nbh);
268 if (functor.inqueue_p_wrt_input_p_(p.val()))
270 dmap.element(p.offset()) = 0;
272 if (functor.inqueue_p_wrt_input_n_(n.val()))
274 bucket[0].push_back(p.offset());
285 for (
unsigned d = 0; bucket_size != 0; ++d)
287 bucket_t& bucket_d = bucket[d % mod];
288 for (
unsigned i = 0; i < bucket_d.size(); ++i)
292 if (dmap.element(p) == max)
295 bucket_size = bucket_d.size();
299 if (dmap.element(p) < d)
303 for (
unsigned i = 0; i < n_ws; ++i)
305 unsigned q = p + dp[i];
306 if (dmap.element(q) > d)
308 unsigned d_ = d + w_win.w(i);
309 if (d_ < dmap.element(q))
311 dmap.element(q) = d_;
312 functor.process_(p, q);
313 bucket[d_ % mod].push_back(q);
319 bucket_size -= bucket_d.size();
324 trace::exiting(
"canvas::impl::distance_front_fastest");
338 template <
typename I,
339 typename N,
typename W,
typename D,
343 distance_front_dispatch(metal::false_,
344 const Image<I>& input,
345 const Neighborhood<N>& nbh, const Weighted_Window<W>& w_win,
348 return impl::generic::distance_front(input, nbh, w_win, max, functor);
351 template <
typename I,
352 typename N,
typename W,
typename D,
356 distance_front_dispatch(metal::true_,
357 const Image<I>& input,
358 const Neighborhood<N>& nbh, const Weighted_Window<W>& w_win,
361 return impl::distance_front_fastest(input, nbh, w_win, max, functor);
364 template <
typename I,
365 typename N,
typename W,
typename D,
369 distance_front_dispatch(const Image<I>& input,
370 const Neighborhood<N>& nbh, const Weighted_Window<W>& w_win,
374 test = mlc_equal(mln_trait_image_speed(I),
375 trait::image::speed::fastest)::
value
377 mln_is_simple_neighborhood(N)::
value
379 mln_is_simple_weighted_window(W)::
value
381 return distance_front_dispatch(metal::bool_<test>(),
382 input, nbh, w_win, max, functor);
392 template <
typename I,
393 typename N,
typename W,
typename D,
401 trace::entering(
"canvas::distance_front");
403 internal::distance_front_tests(input, nbh, w_win, max, functor);
405 mln_ch_value(I,D) output;
406 output = internal::distance_front_dispatch(input, nbh, w_win, max, functor);
408 trace::exiting(
"canvas::distance_front");
413 # endif // ! MLN_INCLUDE_ONLY
420 #endif // ! MLN_CANVAS_DISTANCE_FRONT_HH