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>
55 template <
typename I,
typename N,
typename D,
63 # ifndef MLN_INCLUDE_ONLY
71 template <
typename I,
typename N,
typename D,
74 distance_geodesic_tests(
const Image<I>& input_,
75 const Neighborhood<N>& nbh_, D max,
78 const I& input =
exact(input_);
79 const N& nbh =
exact(nbh_);
81 mln_precondition(input.is_valid());
82 mln_precondition(nbh.is_valid());
103 template <
typename I,
typename N,
typename D,
109 mln_trace(
"canvas::impl::generic::distance_geodesic");
111 const I& input =
exact(input_);
112 const N& nbh =
exact(nbh_);
114 internal::distance_geodesic_tests(input, nbh, max, functor);
116 mln_precondition(input.is_valid());
117 mln_precondition(nbh.is_valid());
119 mln_ch_value(I, D) dmap;
122 typedef mln_site(I) P;
130 mln_piter(I)
p(input.domain());
131 mln_niter(N) n(nbh,
p);
133 if (functor.inqueue_p_wrt_input_p(input(p)))
138 if (input.domain().has(n) &&
139 functor.inqueue_p_wrt_input_n(input(n)))
150 mln_niter(N) n(nbh, p);
151 while (! q.is_empty())
161 if (input.domain().has(n) && dmap(n) == max)
163 dmap(n) = dmap(p) + 1;
164 functor.process(p, n);
179 template <
typename I,
typename N,
typename D,
182 distance_geodesic_fastest(const Image<I>& input_,
183 const Neighborhood<N>& nbh_,
187 mln_trace(
"canvas::impl::distance_geodesic_fastest");
189 const I& input =
exact(input_);
190 const N& nbh =
exact(nbh_);
192 internal::distance_geodesic_tests(input, nbh, max, functor);
196 mln_ch_value(I, D) dmap;
199 std::queue<
unsigned> q;
203 functor.init_(input);
209 mln_pixter(
const I) p(input);
210 mln_nixter(const I, N) n(p, nbh);
212 if (functor.inqueue_p_wrt_input_p_(p.val()))
215 dmap.element(p.offset()) = 0;
217 if (functor.inqueue_p_wrt_input_n_(n.val()))
229 util::array<int>
dp = offsets_wrt(input, nbh);
230 const unsigned n_nbhs = dp.nelements();
236 if (dmap.element(p) ==
max)
239 for (
unsigned i = 0; i < n_nbhs; ++i)
241 unsigned n = p + dp[i];
242 if (dmap.element(n) ==
max)
244 dmap.element(n) = dmap.element(p) + 1;
245 functor.process_(p, n);
265 template <
typename I,
typename N,
typename D,
269 distance_geodesic_dispatch(metal::false_,
270 const Image<I>& input,
271 const Neighborhood<N>& nbh, D max,
278 template <
typename I,
typename N,
typename D,
282 distance_geodesic_dispatch(metal::true_,
283 const Image<I>& input,
284 const Neighborhood<N>& nbh, D max,
287 return impl::distance_geodesic_fastest(input, nbh, max, functor);
292 template <
typename I,
typename N,
typename D,
296 distance_geodesic_dispatch(const Image<I>& input,
297 const Neighborhood<N>& nbh, D max,
301 test = mlc_equal(mln_trait_image_speed(I),
302 trait::image::speed::fastest)::
value
304 mln_is_simple_neighborhood(N)::
value
306 return distance_geodesic_dispatch(metal::bool_<test>(),
318 template <
typename I,
typename N,
typename D,
325 mln_trace(
"canvas::distance_geodesic");
327 internal::distance_geodesic_tests(input, nbh, max, functor);
329 mln_ch_value(I,D) output;
330 output = internal::distance_geodesic_dispatch(input, nbh, max, functor);
336 # endif // ! MLN_INCLUDE_ONLY
343 #endif // ! MLN_CANVAS_DISTANCE_GEODESIC_HH