27 #ifndef MLN_CANVAS_DISTANCE_GEODESIC_HH
28 # define MLN_CANVAS_DISTANCE_GEODESIC_HH
34 # include <mln/core/concept/image.hh>
35 # include <mln/core/concept/neighborhood.hh>
36 # include <mln/core/routine/duplicate.hh>
38 # include <mln/core/site_set/p_queue_fast.hh>
41 # include <mln/data/fill.hh>
42 # include <mln/extension/adjust_fill.hh>
52 template <
typename I,
typename N,
typename D,
60 # ifndef MLN_INCLUDE_ONLY
68 template <
typename I,
typename N,
typename D,
71 distance_geodesic_tests(
const Image<I>& input_,
72 const Neighborhood<N>& nbh_, D max,
75 const I& input = exact(input_);
76 const N& nbh = exact(nbh_);
78 mln_precondition(input.is_valid());
79 mln_precondition(nbh.is_valid());
100 template <
typename I,
typename N,
typename D,
106 trace::entering(
"canvas::impl::generic::distance_geodesic");
108 const I& input = exact(input_);
109 const N& nbh = exact(nbh_);
111 internal::distance_geodesic_tests(input, nbh, max, functor);
113 mln_precondition(input.is_valid());
114 mln_precondition(nbh.is_valid());
116 mln_ch_value(I, D) dmap;
119 typedef mln_site(I) P;
127 mln_piter(I) p(input.domain());
128 mln_niter(N) n(nbh, p);
130 if (functor.inqueue_p_wrt_input_p(input(p)))
135 if (input.domain().has(n) &&
136 functor.inqueue_p_wrt_input_n(input(n)))
147 mln_niter(N) n(nbh, p);
148 while (! q.is_empty())
158 if (input.domain().has(n) && dmap(n) == max)
160 dmap(n) = dmap(p) + 1;
161 functor.process(p, n);
167 trace::exiting(
"canvas::impl::generic::distance_geodesic");
177 template <
typename I,
typename N,
typename D,
180 distance_geodesic_fastest(const Image<I>& input_,
181 const Neighborhood<N>& nbh_,
185 trace::entering(
"canvas::impl::distance_geodesic_fastest");
187 const I& input = exact(input_);
188 const N& nbh = exact(nbh_);
190 internal::distance_geodesic_tests(input, nbh, max, functor);
194 mln_ch_value(I, D) dmap;
197 std::queue<
unsigned> q;
201 functor.init_(input);
207 mln_pixter(
const I) p(input);
208 mln_nixter(const I, N) n(p, nbh);
210 if (functor.inqueue_p_wrt_input_p_(p.val()))
213 dmap.element(p.offset()) = 0;
215 if (functor.inqueue_p_wrt_input_n_(n.val()))
227 util::array<int> dp = offsets_wrt(input, nbh);
228 const unsigned n_nbhs = dp.nelements();
234 if (dmap.element(p) == max)
237 for (
unsigned i = 0; i < n_nbhs; ++i)
239 unsigned n = p + dp[i];
240 if (dmap.element(n) == max)
242 dmap.element(n) = dmap.element(p) + 1;
243 functor.process_(p, n);
250 trace::exiting(
"canvas::impl::distance_geodesic_fastest");
264 template <
typename I,
typename N,
typename D,
268 distance_geodesic_dispatch(metal::false_,
269 const Image<I>& input,
270 const Neighborhood<N>& nbh, D max,
273 return impl::generic::distance_geodesic(input, nbh, max,
277 template <
typename I,
typename N,
typename D,
281 distance_geodesic_dispatch(metal::true_,
282 const Image<I>& input,
283 const Neighborhood<N>& nbh, D max,
286 return impl::distance_geodesic_fastest(input, nbh, max, functor);
291 template <
typename I,
typename N,
typename D,
295 distance_geodesic_dispatch(const Image<I>& input,
296 const Neighborhood<N>& nbh, D max,
300 test = mlc_equal(mln_trait_image_speed(I),
301 trait::image::speed::fastest)::
value
303 mln_is_simple_neighborhood(N)::
value
305 return distance_geodesic_dispatch(metal::bool_<test>(),
317 template <
typename I,
typename N,
typename D,
324 trace::entering(
"canvas::distance_geodesic");
326 internal::distance_geodesic_tests(input, nbh, max, functor);
328 mln_ch_value(I,D) output;
329 output = internal::distance_geodesic_dispatch(input, nbh, max, functor);
331 trace::exiting(
"canvas::distance_geodesic");
336 # endif // ! MLN_INCLUDE_ONLY
343 #endif // ! MLN_CANVAS_DISTANCE_GEODESIC_HH