26 #ifndef MLN_ACCU_TRANSFORM_SNAKE_HH
27 # define MLN_ACCU_TRANSFORM_SNAKE_HH
39 # include <mln/core/concept/image.hh>
40 # include <mln/core/concept/meta_accumulator.hh>
41 # include <mln/core/alias/window2d.hh>
42 # include <mln/win/diff.hh>
43 # include <mln/win/shift.hh>
44 # include <mln/geom/delta.hh>
45 # include <mln/extension/adjust.hh>
47 # include <mln/canvas/browsing/snake_fwd.hh>
48 # include <mln/canvas/browsing/snake_generic.hh>
59 template <
typename A,
typename I,
typename W>
60 mln_ch_value(I, mln_result(A))
61 transform_snake(const Accumulator<A>& a, const Image<I>& input, const Window<W>& win);
64 template <typename A, typename I, typename W>
66 transform_snake(const Meta_Accumulator<A>& a, const Image<I>& input, const Window<W>& win);
70 # ifndef MLN_INCLUDE_ONLY
76 template <
typename I,
typename W>
77 void transform_snake_tests(
const Image<I>& input_,
const Window<W>& win_)
79 const I& input = exact(input_);
80 const W& win = exact(win_);
82 mln_precondition(input.is_valid());
83 mln_precondition(win.is_valid());
84 mln_precondition(! win.is_empty());
93 template <
typename I,
typename W,
typename A>
94 struct transform_snake_functor
96 typedef transform_snake_functor<I,W, A>
self;
97 typedef void (
self::*move_fun)();
98 typedef mln_deduce(I, psite, delta) dpsite;
104 mln_ch_value(I, mln_result(A)) output;
128 std::vector<move_fun> moves;
129 std::vector<dpsite> dps;
131 transform_snake_functor(const Image<I>& input, const Window<W>& win, const Accumulator<A>& a)
132 : input(exact(input)),
136 win_left_fwd(win::shift(win, mln::left) - win),
137 win_right_fwd(win - win::shift(win, mln::left)),
138 win_left_bkd(win::shift(win_left_fwd, mln::right)),
139 win_right_bkd(win::shift(win_right_fwd, mln::right)),
141 win_bot_up(win::shift(win, mln::down) - win),
142 win_top_up(win - win::shift(win, mln::down)),
143 win_bot_down(win::shift(win_bot_up, mln::
up)),
144 win_top_down(win::shift(win_top_up, mln::up)),
146 q_l_fwd(win_left_fwd, p),
147 q_r_fwd(win_right_fwd, p),
148 q_l_bkd(win_left_bkd, p),
149 q_r_bkd(win_right_bkd, p),
151 q_top_up(win_top_up, p),
152 q_bot_up(win_bot_up, p),
153 q_top_down(win_top_down, p),
154 q_bot_down(win_bot_down, p),
159 if (win_bot_up.size() + win_top_up.size() +
160 win_bot_down.size() + win_top_down.size() <
161 win_left_fwd.size() + win_right_fwd.size() +
162 win_left_bkd.size() + win_right_bkd.size())
168 moves[0] = &self::right;
169 moves[1] = &self::down;
170 moves[2] = &self::up;
178 moves[0] = &self::down;
179 moves[1] = &self::right;
180 moves[2] = &self::left;
188 p = input.domain().pmin() - dps[0];
189 mln_qiter(W) q(win, p);
193 p = input.domain().pmin();
199 if (input.has(q_l_fwd))
200 accu.untake(input(q_l_fwd));
202 if (input.has(q_r_fwd))
203 accu.
take(input(q_r_fwd));
210 if (input.has(q_r_bkd))
211 accu.untake(input(q_r_bkd));
213 if (input.has(q_l_bkd))
214 accu.
take(input(q_l_bkd));
221 if (input.has(q_top_down))
222 accu.untake(input(q_top_down));
224 if (input.has(q_bot_down))
225 accu.
take(input(q_bot_down));
232 if (input.has(q_bot_up))
233 accu.untake(input(q_bot_up));
235 if (input.has(q_top_up))
236 accu.
take(input(q_top_up));
246 template <typename I, typename W, typename A>
247 struct transform_snake_fastest_functor
249 typedef transform_snake_fastest_functor<I,W,A>
self;
250 typedef void (
self::*move_fun)();
251 typedef mln_deduce(I, psite, delta) dpsite;
257 mln_ch_value(I, mln_result(A)) output;
282 std::vector<move_fun> moves;
283 std::vector<dpsite> dps;
285 transform_snake_fastest_functor(const I& input, const W& win, const A& a)
290 win_left_fwd(win::shift(win, mln::left) - win),
291 win_right_fwd(win - win::shift(win, mln::left)),
292 win_left_bkd(win::shift(win_left_fwd, mln::right)),
293 win_right_bkd(win::shift(win_right_fwd, mln::right)),
295 win_bot_up(win::shift(win, mln::down) - win),
296 win_top_up(win - win::shift(win, mln::down)),
297 win_bot_down(win::shift(win_bot_up, mln::up)),
298 win_top_down(win::shift(win_top_up, mln::up)),
300 q_l_fwd(input, win_left_fwd, p),
301 q_r_fwd(input, win_right_fwd, p),
302 q_l_bkd(input, win_left_bkd, p),
303 q_r_bkd(input, win_right_bkd, p),
305 q_top_up(input, win_top_up, p),
306 q_bot_up(input, win_bot_up, p),
307 q_top_down(input, win_top_down, p),
308 q_bot_down(input, win_bot_down, p),
313 if (win_bot_up.size() + win_top_up.size() +
314 win_bot_down.size() + win_top_down.size() <
315 win_left_fwd.size() + win_right_fwd.size() +
316 win_left_bkd.size() + win_right_bkd.size())
322 moves[0] = &self::right;
323 moves[1] = &self::down;
324 moves[2] = &self::up;
332 moves[0] = &self::down;
333 moves[1] = &self::right;
334 moves[2] = &self::left;
345 p = input.domain().pmin() - dps[0];
346 mln_qixter(
const I, W) q(input, win, p);
349 p = input.domain().pmin();
355 accu.untake(q_l_fwd.val());
357 accu.
take(q_r_fwd.val());
364 accu.untake(q_r_bkd.val());
366 accu.
take(q_l_bkd.val());
373 accu.untake(q_top_down.val());
375 accu.
take(q_bot_down.val());
382 accu.untake(q_bot_up.val());
384 accu.
take(q_top_up.val());
393 template <typename A, typename I, typename W>
395 mln_ch_value(I, mln_result(A))
396 transform_snake_dispatch(metal::false_,
397 const Accumulator<A>& a,
398 const Image<I>& input, const Window<W>& win)
400 typedef transform_snake_functor<I, W, A> F;
401 F f(exact(input), exact(win), exact(a));
402 canvas::browsing::snake_generic(f);
406 template <
typename A,
typename I,
typename W>
408 mln_ch_value(I, mln_result(A))
409 transform_snake_dispatch(metal::true_,
410 const Accumulator<A>& a,
411 const Image<I>& input, const Window<W>& win)
413 typedef transform_snake_fastest_functor<I, W, A> F;
414 F f(exact(input), exact(win), exact(a));
415 canvas::browsing::snake_generic(f);
419 template <
typename A,
typename I,
typename W>
421 mln_ch_value(I, mln_result(A))
422 transform_snake_dispatch(const Accumulator<A>& a,
423 const Image<I>& input, const Window<W>& win)
425 return transform_snake_dispatch(mln_is_fastest_IW(I, W)(),
434 template <
typename A,
typename I,
typename W>
436 mln_ch_value(I, mln_result(A))
437 transform_snake(const Accumulator<A>& a,
438 const Image<I>& input, const Window<W>& win)
440 trace::entering(
"accu::transform_snake");
442 internal::transform_snake_tests(input, win);
445 mln_ch_value(I, mln_result(A)) output;
446 output = internal::transform_snake_dispatch(a, input, win);
448 trace::exiting("accu::transform_snake");
453 template <typename A, typename I, typename W>
456 transform_snake(const Meta_Accumulator<A>& a,
457 const Image<I>& input, const Window<W>& win)
459 trace::entering(
"accu::transform_snake");
461 internal::transform_snake_tests(input, win);
463 typedef mln_accu_with(A, mln_value(I)) A_;
464 A_ a_ = accu::unmeta(exact(a), mln_value(I)());
466 extension::adjust(input, geom::delta(win) + 1);
467 mln_ch_value(I, mln_result(A_)) output;
468 output = internal::transform_snake_dispatch(a_, input, win);
470 trace::exiting("accu::transform_snake");
475 # endif // ! MLN_INCLUDE_ONLY
482 #endif // ! MLN_ACCU_TRANSFORM_SNAKE_HH